earendil-works/pi · error · ExecutionError

timeout

timeout

Error message

Invalid timeout: must be a finite number of seconds

What it means

Validation error from resolveTimeoutMs: the caller-supplied shell-exec timeout option is not a finite positive number of seconds (NaN, Infinity, zero, or negative). It is converted into an ExecutionError of kind 'timeout' before any child process is spawned, so an unusable timer never reaches setTimeout.

Solutions

  1. Pass a finite number of seconds as the timeout.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/agent/src/harness/env/nodejs.ts:41 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of earendil-works/pi@4af9d21d3b (2026-08-24). Data as JSON: /api/errors/53462af083fd666a. Report an issue: GitHub.

Appendix: source

Thrown at packages/agent/src/harness/env/nodejs.ts:41

	ExecutionError,
	err,
	FileError,
	type FileInfo,
	type FileKind,
	ok,
	type Result,
	type ShellExecOptions,
	toError,
} from "../types.ts";

const MAX_TIMEOUT_MS = 2_147_483_647;
const MAX_TIMEOUT_SECONDS = MAX_TIMEOUT_MS / 1000;
const EXIT_STDIO_GRACE_MS = 100;

function resolveTimeoutMs(timeout: number | undefined): Result<number | undefined, ExecutionError> {
	if (timeout === undefined) return ok(undefined);
	if (!Number.isFinite(timeout) || timeout <= 0) {
		return err(new ExecutionError("timeout", "Invalid timeout: must be a finite number of seconds"));
	}

	const timeoutMs = timeout * 1000;
	if (timeoutMs > MAX_TIMEOUT_MS) {
		return err(new ExecutionError("timeout", `Invalid timeout: maximum is ${MAX_TIMEOUT_SECONDS} seconds`));
	}
	return ok(timeoutMs);
}

function resolvePath(cwd: string, path: string): string {
	let normalized = path;
	if (normalized === "~") {
		normalized = homedir();
	} else if (normalized.startsWith("~/") || (process.platform === "win32" && normalized.startsWith("~\\"))) {
		normalized = join(homedir(), normalized.slice(2));
	} else if (normalized.startsWith("file://")) {
		try {
			normalized = fileURLToPath(normalized);

View on GitHub (pinned to 4af9d21d3b)