n8n-io/n8n · error

Daytona sandbox "${this.id}" is not running

Error message

Daytona sandbox "${this.id}" is not running

What it means

DaytonaSandbox.instance is a getter that returns the underlying Daytona SDK `Sandbox` object. If `this.sandbox` is null/undefined it throws, because start() either was never called, failed before assignment, or destroy() cleared it. The getter exists to give internal methods a non-null handle without sprinkling null checks at every call site.

Source

Thrown at packages/@n8n/agents/src/workspace/sandbox/daytona-sandbox.ts:190

		super();
		this.id = options.id ?? `daytona-sandbox-${randomUUID()}`;
		this.timeout = options.timeout ?? 300_000;
		this.language = options.language ?? 'typescript';
		this.sandboxName = options.name ?? this.id;
		this.auth = new DaytonaAuthManager({
			apiUrl: options.apiUrl,
			target: options.target,
			staticApiKey: options.apiKey,
			getAuthToken: options.getAuthToken,
			refreshSkewMs: options.refreshSkewMs,
			logger: options.logger,
			sandboxName: this.sandboxName,
		});
	}

	get instance(): Sandbox {
		if (!this.sandbox) {
			throw new Error(`Daytona sandbox "${this.id}" is not running`);
		}
		return this.sandbox;
	}

	override async start(): Promise<void> {
		if (this.sandbox) return;

		const client = await this.getDaytona();
		const existing = await this.findExistingSandbox(client);
		if (existing) {
			this.sandbox = existing;
			await this.detectWorkingDirectory();
			return;
		}

		this.sandbox = await this.createSandboxOrReattach(client);
		await this.detectWorkingDirectory();
	}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Always `await sandbox.start()` before any other operation, and let start errors propagate.
  2. Don't access .instance directly — go through ensureRunning()/executeCommand() which guard state first.
  3. After stop()/destroy(), create a new DaytonaSandbox rather than reusing.

Example fix

// before
const sb = new DaytonaSandbox(opts);
const info = await sb.instance.getInfo(); // start not awaited

// after
const sb = new DaytonaSandbox(opts);
await sb.start();
const info = await sb.instance.getInfo();
Defensive patterns

Strategy: validation

Validate before calling

function isStarted(sandbox: { instance?: unknown }): boolean {
  return Boolean(sandbox.instance);
}
// ensure the sandbox is started before any op:
if (!sandbox['sandbox']) await sandbox.start();

Try / catch

try {
  await sandbox.start();
  return sandbox.instance;
} catch (e) {
  if (e instanceof Error && /is not running/.test(e.message)) {
    // start failed — recreate the DaytonaSandbox
  } else throw e;
}

Prevention

When it happens

Trigger: Accessing `sandbox.instance` before start() resolved; after start() failed (findExistingSandbox/createSandbox threw) leaving this.sandbox unset; after stop()/destroy() cleared the reference; calling a method that uses `instance` without first ensuring running.

Common situations: Calling executeCommand/processes before awaiting start(); a start failure that was swallowed; using the sandbox after stop.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/4b530d4269975f4c. Report an issue: GitHub.