windmill-labs/windmill · error · Error

Job ${jobId} was not successful: ${JSON.stringify(error)}

Error message

Job ${jobId} was not successful: ${JSON.stringify(error)}

What it means

Thrown by waitJob when the polled job completed with success=false. The job's own `error` field is JSON-serialized into the message, so the text carries the underlying run failure (script exception, invalid args, worker error) — this is the client surfacing a failed execution, not a client-side fault.

Source

Thrown at typescript-client/client.ts:306

  while (true) {
    // Implement your HTTP request logic here to get job result
    const resultRes = await getResultMaybe(jobId);

    const started = resultRes.started;
    const completed = resultRes.completed;
    const success = resultRes.success;

    if (!started && verbose) {
      console.info(`job ${jobId} has not started yet`);
    }

    if (completed) {
      const result = resultRes.result;
      if (success) {
        return result;
      } else {
        const error = result.error;
        throw new Error(
          `Job ${jobId} was not successful: ${JSON.stringify(error)}`
        );
      }
    }

    if (verbose) {
      console.info(`sleeping 0.5 seconds for jobId: ${jobId}`);
    }

    await new Promise((resolve) => setTimeout(resolve, 500));
  }
}

/**
 * Get the result of a completed job
 * @param jobId - ID of the completed job
 * @returns Job result
 */

View on GitHub (pinned to e474e8803c)

Solutions

  1. Read the JSON error payload in the message to find the actual failure cause
  2. Fix the bug in the script/flow that made the run fail
  3. Wrap the call in try/catch if failure is expected and handle the error object
  4. Re-run with verbose logging to see intermediate job state

Example fix

// before
const result = await client.runScriptByPath('etl/job', args)
// after
try {
  const result = await client.runScriptByPath('etl/job', args)
} catch (e) {
  console.error('job failed:', e.message) // includes job id + server error JSON
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const result = await client.runScriptByPath(path, args)
} catch (e) {
  if (String(e.message).startsWith('Job ') && e.message.includes('was not successful')) {
    const payload = JSON.parse(e.message.slice(e.message.indexOf('{')))
    console.error('Job failed on server:', payload)
  } else throw e
}

Prevention

When it happens

Trigger: Calling runScript*/runFlow* (which await waitJob) when the underlying script/flow execution fails — e.g. an uncaught exception in the script, a failed flow step, or a denied/precondition failure.

Common situations: Bugs in the executed script or flow; missing resource/variable at runtime; invalid inputs causing the run to error; flow routing to a failure branch.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/32573116745e922f. Report an issue: GitHub.