logo

Failures, on_end and limits

A build action is part of your build. When it fails, the build fails, and the log tells you which script, why, and the last lines it printed. on_end is the one hook that always runs, so it is where you report the result.

When a script fails

Any error in a script fails the build. That includes an uncaught exception, a syntax error, a missing import, a non-zero exit code, a crash, and running too long. Output on stderr with exit code 0 counts as success.

Where the failure shows

  1. Your script's full output in the build log under build action <hook>, including the whole Python traceback or Node stack trace.
  2. The build action <hook> step marked failed on the build page.
  3. A summary at the end of the log that repeats the last lines of your script's error output:
Build log
=== BUILD ACTION FAILED: pre_build (.dsl/build_actions/pre_build.py) ===
reason:   exited with code 1
runtime:  python 3.14.7                 cwd: <project folder>
duration: 4.2 s
last lines of stderr:
  Traceback (most recent call last):
    File ".../.dsl/build_actions/pre_build.py", line 12, in <module>
  FileNotFoundError: [Errno 2] No such file or directory: 'Assets/Gen/config.json'

Reading the build log and its steps is covered in Your first build.

Fail a build on purpose

Exit non-zero: sys.exit(1) in Python or process.exit(1) in Node. Use it for checks that should stop a build, such as a missing asset or a version that does not match.

Platform faults

Reporting results with on_end

on_end always runs last and is told how the build went:

Variables only on_end receives
VariableValue
DSL_BUILD_RESULTsuccess, failed, or exception (a platform error)
DSL_FAILED_PHASEThe step that failed, e.g. build or build action pre_build
DSL_FAILURE_MESSAGEThe one-line reason

This on_end.py posts the result to a chat webhook whose URL is stored as the secret CHAT_WEBHOOK_URL (see Secrets in build actions):

on_end.py
# .dsl/build_actions/on_end.py - post the result to a chat webhook
import json, os, urllib.request

secrets = json.load(open(os.environ["DSL_SECRETS_FILE"]))
result = os.environ["DSL_BUILD_RESULT"]
text = f'{os.environ["DSL_PROJECT"]} {os.environ["DSL_VERSION"]}.{os.environ["DSL_BUILD_NUMBER"]} ({os.environ["DSL_CONFIGURATION"]}): {result}'
if result != "success":
    text += f' - {os.environ.get("DSL_FAILED_PHASE", "")}: {os.environ.get("DSL_FAILURE_MESSAGE", "")}'

req = urllib.request.Request(secrets["CHAT_WEBHOOK_URL"], data=json.dumps({"text": text}).encode(),
                             headers={"Content-Type": "application/json"})
urllib.request.urlopen(req, timeout=30)

on_end does not run when a build is canceled or interrupted by maintenance.

Limits

Build action limits
LimitValue
Time per script30 minutes
No output15 minutes: a script that prints nothing for that long is stopped
Scripts per hook1

A script stopped by a limit fails the build, and the log names the limit it hit. For long work, split it across hooks or print progress as you go.

Something out of date or unclear? Email support@devstreamlabs.com.