can1357/oh-my-pi · error · ToolError
ready.port must be an integer from 1 to 65535
Error message
ready.port must be an integer from 1 to 65535
What it means
When start params include a `ready` condition, ready.port must be a valid TCP port: an integer in 1–65535. commandSpec() throws this ToolError when ready.port is present but fails that check (non-integer, 0, negative, or above 65535).
Source
Thrown at packages/coding-agent/src/tools/hub/launch.ts:188
}
function requiredName(params: LaunchParams): string {
if (!params.name) throw new ToolError(`${params.op} requires name`);
return params.name;
}
function timeoutMs(value: number | undefined, fallbackSeconds: number): number {
const seconds = Math.max(0.05, Math.min(3_600, value ?? fallbackSeconds));
return Math.round(seconds * 1_000);
}
function commandSpec(params: LaunchParams, session: ToolSession): DaemonSpec {
const name = requiredName(params);
if (!params.application) throw new ToolError("start requires application");
const ready = params.ready;
const detached = params.detached ?? false;
if (ready?.port !== undefined && (!Number.isInteger(ready.port) || ready.port < 1 || ready.port > 65_535)) {
throw new ToolError("ready.port must be an integer from 1 to 65535");
}
if (ready && !ready.log && ready.port === undefined) throw new ToolError("ready requires log or port");
return {
name,
application: params.application,
args: params.args ?? [],
env: params.env ?? {},
cwd: resolveToCwd(params.cwd ?? session.cwd, session.cwd),
pty: detached ? false : (params.pty ?? true),
ready: ready
? {
log: ready.log,
port: ready.port,
host: ready.host,
timeoutMs: timeoutMs(ready.timeout, 30),
}
: undefined,
restart: params.restart ?? "no",View on GitHub (pinned to 9690622007)
Solutions
- Set ready.port to an integer between 1 and 65535 (e.g. 8080).
- Coerce string ports to integers first: Number.parseInt(value, 10).
- If you don't know the port yet, rely on ready.log matching instead of ready.port.
Example fix
// before
launch({ op: "start", name: "api", application: "bun", ready: { port: "8080" } })
// throws: ready.port must be an integer from 1 to 65535
// after
launch({ op: "start", name: "api", application: "bun", ready: { port: 8080 } }) Defensive patterns
Strategy: validation
Validate before calling
const port = params.ready?.port;
if (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65535)) {
throw new Error("ready.port must be an integer from 1 to 65535");
} Type guard
function isValidPort(p: unknown): p is number {
return typeof p === "number" && Number.isInteger(p) && p >= 1 && p <= 65535;
} Try / catch
try {
await launchTool.run({ op: "start", name, application, ready });
} catch (err) {
if (err instanceof ToolError && err.message.includes("ready.port must be an integer")) {
// coerce/fix the port and retry
} else throw err;
} Prevention
- Parse config/env ports with Number.parseInt before use.
- Never use 0 or 'any port' for readiness checks.
- Type ready.port as a strict integer in your tool-arg builders.
When it happens
Trigger: launch({ op: "start", name, application, ready: { port: 0 } }), port: 70000, port: 8080.5, or a string like "8080" that is not an integer.
Common situations: Passing a port as a string from config/env interpolation; using 0 to mean 'any port' (unsupported — readiness needs a concrete port); fat-fingered port numbers beyond the 16-bit range.
Related errors
- ssh://: invalid host or port in "${url.href}"; use ssh://hos
- ${params.op} requires name
- start requires application
- ready requires log or port
- Unsupported launch key ${rawKey}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f2f7375158a41b0a.
Report an issue: GitHub.