different-ai/openwork · error · Error

Desktop Automation execution timed out

Error message

Desktop Automation execution timed out

What it means

The polling loop in executeDesktopAutomation enforces assignment.timeoutMs via a wall-clock deadline checked at the top of every iteration. If the assistant thread has not produced a terminal result before the deadline, execution is abandoned with this timeout error (the thread is aborted via the registered abort listener).

Source

Thrown at apps/desktop/electron/automation-runner.mjs:179

  const workspace = resolveAssignmentWorkspace(listed, assignment.workspaceId ?? null)
  const workspaceId = String(workspace.id)
  const client = createWorkspaceSessionClient(local, workspaceId, options.fetchImpl ?? fetch)
  const created = await client.createThread({
    title: `Automation: ${assignment.automationName}`.slice(0, 120),
    ...(assignment.instructions ? { prompt: assignment.instructions } : {}),
    model: assignment.model,
    signal: options.signal,
  })
  const sessionId = created.id
  // The assignment signal is already aborted when this listener runs. Do not
  // pass it to the cleanup request or fetch can reject before reaching OpenCode.
  const abort = () => void client.abortThread(sessionId).catch(() => undefined)
  options.signal.addEventListener("abort", abort, { once: true })
  try {
    const startedAt = Date.now()
    const deadlineAt = startedAt + assignment.timeoutMs
    while (true) {
      if (Date.now() > deadlineAt) throw new Error("Desktop Automation execution timed out")
      // The wall-clock check above only runs between awaits. A machine that
      // suspends mid-request can leave this socket half-open with no error,
      // which would make the assignment timeout unreachable: bound each poll
      // by the remaining execution budget so the deadline always fires.
      let snapshot
      try {
        snapshot = await client.getThreadSnapshot(sessionId, {
          signal: AbortSignal.any([options.signal, AbortSignal.timeout(Math.max(1, deadlineAt - Date.now()))]),
          limit: 200,
        })
      } catch (error) {
        if (!options.signal.aborted && Date.now() >= deadlineAt) throw new Error("Desktop Automation execution timed out")
        throw error
      }
      const output = assistantResult(snapshot)
      const snapshotError = assistantFailure(snapshot)
      if (snapshotError) {
        const error = new Error(snapshotError.message)

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Increase assignment.timeoutMs to cover the expected task duration
  2. Investigate why the thread never went idle/produced a result (check session logs)
  3. Break the task into smaller assignments with shorter scopes
  4. Check for permission prompts blocking the automated thread

Example fix

// before: default 60s timeout for a long research task
const assignment = { prompt: "deep research...", timeoutMs: 60_000 };
// after
const assignment = { prompt: "deep research...", timeoutMs: 15 * 60_000 };
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the budget covers the task before submitting
const estimatedMs = estimateTaskDuration(assignment.prompt);
if (estimatedMs >= assignment.timeoutMs) {
  assignment.timeoutMs = Math.max(assignment.timeoutMs, estimatedMs * 2);
}

Try / catch

try {
  const result = await executeDesktopAutomation(assignment, options);
} catch (err) {
  if (err.message === "Desktop Automation execution timed out") {
    // thread already aborted; retry with a larger budget
    await executeDesktopAutomation({ ...assignment, timeoutMs: assignment.timeoutMs * 2 }, options);
  } else throw err;
}

Prevention

When it happens

Trigger: getThreadSnapshot polling looped past startedAt + assignment.timeoutMs without the thread reaching a result — e.g. the agent task legitimately runs longer than the configured timeout, or polling stalls.

Common situations: Assignment timeoutMs configured too low for a long-running agent task; agent stuck waiting on user input/permission prompt; slow model responses; machine under heavy load slowing execution.

Understand the failure class

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/e7e4a0c826c6b72f. Report an issue: GitHub.