paperclipai/paperclip · error

turnStartTimeoutMs must be a positive safe integer

Error message

turnStartTimeoutMs must be a positive safe integer

What it means

Options guard in #startTurn of the runnerd Codex transport: the configured turnStartTimeoutMs (default 30000) is not a positive safe integer. This is a configuration error in the transport options object, validated before any turn is started.

Solutions

  1. Set turnStartTimeoutMs to a positive integer below Number.MAX_SAFE_INTEGER
  2. Remove the option to use the 30s default
  3. Fix the config source that produced NaN, zero, negative, or fractional values
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:5299 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-10). Data as JSON: /api/errors/e9ba9582e67472e8. Report an issue: GitHub.

Appendix: source

Thrown at packages/paperclip-runner/src/live/runnerd-codex-transport.ts:5479

        },
        ...(call.sourceEventId && call.sourceEventType
          ? {
              paperclipTrace: {
                sourceEventId: call.sourceEventId,
                sourceEventType: call.sourceEventType,
              },
            }
          : {}),
      }),
    );
  }

  async #startTurn(
    params: Record<string, unknown>,
  ): Promise<Record<string, unknown>> {
    const turnStartTimeoutMs = this.options.turnStartTimeoutMs ?? 30_000;
    if (!Number.isSafeInteger(turnStartTimeoutMs) || turnStartTimeoutMs <= 0) {
      throw new Error("turnStartTimeoutMs must be a positive safe integer");
    }
    const commandDeadline = Date.now() + turnStartTimeoutMs;
    const input = Array.isArray(params.input) ? params.input.map(record) : [];
    const message = input
      .filter((item) => item.type !== "skill")
      .map((item) => (typeof item.text === "string" ? item.text : ""))
      .join("\n");
    const skills = resolveRunnerdCodexSkillInputs(
      input.filter((item) => item.type === "skill"),
      this.options.runtimeContext ?? null,
      resolve(this.options.runnerFilesystemRoot ?? this.#root, "codex-home"),
    );
    if (skills.length && (this.options.provider ?? "codex") !== "codex") {
      throw new Error("Explicit skill inputs are supported only by Codex");
    }
    const pendingTurnId = `turn_lab_${randomUUID().replaceAll("-", "")}`;
    this.#turnId = pendingTurnId;
    const responseEpoch = ++this.#turnStartResponseEpoch;

View on GitHub (pinned to 3f1d897a7c)