windmill-labs/windmill · error · Exception
Result was none
Error message
Result was none
What it means
wait_job polls a job until completion; when the job succeeds but its result is null and `assert_result_is_not_none=True`, the client raises 'Result was none'. It guards callers that require a meaningful return value from the script/flow.
Source
Thrown at python-client/wmill/wmill/client.py:430
result_res = self.get(
f"/w/{self.workspace}/jobs_u/completed/get_result_maybe/{job_id}", True
).json()
started = result_res["started"]
completed = result_res["completed"]
success = result_res["success"]
if not started and verbose:
logger.info(f"job {job_id} has not started yet")
if cleanup and completed:
atexit.unregister(cancel_job)
if completed:
result = result_res["result"]
if success:
if result is None and assert_result_is_not_none:
raise Exception("Result was none")
return result
else:
error = result["error"]
raise Exception(f"Job {job_id} was not successful: {str(error)}")
if timeout and ((time.time() - start_time) > timeout):
msg = "reached timeout"
logger.warning(msg)
self.post(
f"/w/{self.workspace}/jobs_u/queue/cancel/{job_id}",
json={"reason": msg},
)
raise TimeoutError(msg)
if verbose:
logger.info(f"sleeping 0.5 seconds for {job_id = }")
time.sleep(0.5)
View on GitHub (pinned to e474e8803c)
Solutions
- Add a return value to the script (Python: `return {...}` as the last statement; TypeScript: return an object).
- Set assert_result_is_not_none=False if a None result is acceptable.
- Check the job's result in the UI/runs page to confirm what the script actually returned.
Example fix
// before (script)
def main():
do_work() # no return -> result None
// after (script)
def main():
result = do_work()
return result
// caller
result = client.wait_job(job_id, assert_result_is_not_none=True) Defensive patterns
Strategy: try-catch
Validate before calling
# before asserting, inspect the job result
completed = client.get_job(job_id)
if completed.get('success') and completed.get('result') is None:
logger.warning('job %s returned None; fix the script to return a value', job_id) Type guard
def has_result(job_result) -> bool:
return job_result is not None Try / catch
try:
result = client.wait_job(job_id, assert_result_is_not_none=True)
except Exception as e:
if str(e) == 'Result was none':
result = default_value_or_retry()
else:
raise Prevention
- Ensure every waited script ends with an explicit return statement.
- Only set assert_result_is_not_none=True for scripts guaranteed to return values.
- Test scripts standalone in the UI to confirm their result before chaining them.
- Side-effect-only scripts should not assert a non-None result.
When it happens
Trigger: Calling wait_job(job_id, assert_result_is_not_none=True) on a job whose script finished successfully but returned None (script has no return/last expression, or explicitly returns None).
Common situations: Python script missing a final `return` statement so the job result is null; script intentionally side-effect-only but caller still asserts non-None; flow whose last step produces no output.
Related errors
- result is None for {job_id = }
- Job {job_id} was not successful: {str(error)}
- reached timeout
- could not read the run of job ${id}: ${res.status} ${await r
- could not record run ${experiment_id}: ${res.status} ${await
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/0801d2276083d674.
Report an issue: GitHub.