mastra-ai/mastra · error

Unable to read worker ${stream}.

Error message

Unable to read worker ${stream}.

What it means

readOutput tails a worker output stream file inside the sandbox over a shell command (wc -c + tail + base64). If the command exits non-zero and neither stderr nor stdout carries a usable message, the library throws this generic 'Unable to read worker <stream>' error indicating the output file could not be read.

Source

Thrown at deployers/sandbox/src/worker.ts:679

  sandbox: WorkspaceSandbox,
  executionId: string,
  resolvePaths: () => Promise<ReturnType<typeof executionPaths>>,
  stream: 'stdout' | 'stderr',
  options?: { offset?: number; maxBytes?: number },
): Promise<SandboxWorkerOutput> {
  const offset = Math.max(0, Math.floor(options?.offset ?? 0));
  const maxBytes = Math.max(1, Math.floor(options?.maxBytes ?? DEFAULT_OUTPUT_READ_LIMIT));
  try {
    const paths = await resolvePaths();
    const path = stream === 'stdout' ? paths.stdout : paths.stderr;
    const result = await runInSandbox(
      sandbox,
      `size=$(wc -c < ${shellQuote(path)} 2>/dev/null || echo 0); printf '%s\\n' "$size"; tail -c +${offset + 1} ${shellQuote(
        path,
      )} 2>/dev/null | head -c ${maxBytes} | base64`,
      { allowFailure: true, label: `read worker ${stream}` },
    );
    if (result.exitCode !== 0) throw new Error(result.stderr || result.stdout || `Unable to read worker ${stream}.`);
    const newline = result.stdout.indexOf('\n');
    const totalBytes = Number((newline === -1 ? result.stdout : result.stdout.slice(0, newline)).trim()) || 0;
    const encoded = newline === -1 ? '' : result.stdout.slice(newline + 1).replace(/\s/g, '');
    const data = Buffer.from(encoded, 'base64');
    const nextOffset = offset + data.byteLength;
    const status = await readWorkerStatus(sandbox, executionId, resolvePaths);
    const terminal = ['exited', 'resource_exhausted', 'cancelled', 'timed_out', 'failed'].includes(status.state);
    const interrupted = status.state === 'provider_unavailable' || status.state === 'unknown';
    return {
      stream,
      data,
      offset,
      nextOffset,
      totalBytes,
      eof: terminal && nextOffset >= totalBytes,
      truncated: nextOffset < totalBytes,
      interrupted,
    };

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Check result.stderr in the error message (it is preferred over stdout) — it usually contains the shell-level failure reason.
  2. Verify the worker actually ran and produced the output file at the resolved path (inspect sandbox filesystem).
  3. Confirm remoteDir/execution paths resolve to the expected location in the sandbox config.
  4. Check sandbox file permissions on the output file and the sandbox process's liveness.
  5. Retry the read; transient provider failures can make the shell command exit non-zero.

Example fix

// before
const { data } = await worker.output('stdout', { offset });
// after
try {
  const { data } = await worker.output('stdout', { offset });
} catch (e) {
  if (String(e).includes('Unable to read worker')) {
    const status = await worker.status();
    if (status.state !== 'running') throw new Error(`Worker not running: ${status.state}`);
  }
  throw e;
}
Defensive patterns

Strategy: retry

Validate before calling

// before reading output, confirm the worker is alive and paths resolve
const status = await worker.status();
if (status.state === 'failed' || status.state === 'canceled') throw new Error('worker not producing output: ' + status.state);

Type guard

function workerCanProduceOutput(status) { return status != null && ['running', 'completed', 'succeeded'].includes(status.state); }

Try / catch

try {
  const out = await worker.output(stream, { offset });
} catch (e) {
  if (/Unable to read worker/.test(e.message)) {
    await sleep(backoff);
    return worker.output(stream, { offset }); // bounded retry for transient provider failures
  } else throw e;
}

Prevention

When it happens

Trigger: Calling workerDeployment.output(...) / readOutput when the shell read fails: output file path missing or unreadable under the resolved paths, sandbox command execution failing (permissions, dead sandbox), or the provider returning a non-zero exit code for the read command.

Common situations: Worker never created the output file because it crashed before writing; incorrect remoteDir/paths resolution; sandbox restarted and tmp files wiped; restrictive file permissions (note stageInput chmods input 600 — analogous permission issues on output); sandbox provider connectivity flakiness.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/fd50ca2aea0e0650. Report an issue: GitHub.