{"record":{"id":"f2f7375158a41b0a","repo":"can1357/oh-my-pi","slug":"ready-port-must-be-an-integer-from-1-to-65535","errorCode":null,"errorMessage":"ready.port must be an integer from 1 to 65535","messagePattern":"ready\\.port must be an integer from 1 to 65535","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/hub/launch.ts","lineNumber":188,"sourceCode":"}\n\nfunction requiredName(params: LaunchParams): string {\n\tif (!params.name) throw new ToolError(`${params.op} requires name`);\n\treturn params.name;\n}\n\nfunction timeoutMs(value: number | undefined, fallbackSeconds: number): number {\n\tconst seconds = Math.max(0.05, Math.min(3_600, value ?? fallbackSeconds));\n\treturn Math.round(seconds * 1_000);\n}\n\nfunction commandSpec(params: LaunchParams, session: ToolSession): DaemonSpec {\n\tconst name = requiredName(params);\n\tif (!params.application) throw new ToolError(\"start requires application\");\n\tconst ready = params.ready;\n\tconst detached = params.detached ?? false;\n\tif (ready?.port !== undefined && (!Number.isInteger(ready.port) || ready.port < 1 || ready.port > 65_535)) {\n\t\tthrow new ToolError(\"ready.port must be an integer from 1 to 65535\");\n\t}\n\tif (ready && !ready.log && ready.port === undefined) throw new ToolError(\"ready requires log or port\");\n\treturn {\n\t\tname,\n\t\tapplication: params.application,\n\t\targs: params.args ?? [],\n\t\tenv: params.env ?? {},\n\t\tcwd: resolveToCwd(params.cwd ?? session.cwd, session.cwd),\n\t\tpty: detached ? false : (params.pty ?? true),\n\t\tready: ready\n\t\t\t? {\n\t\t\t\t\tlog: ready.log,\n\t\t\t\t\tport: ready.port,\n\t\t\t\t\thost: ready.host,\n\t\t\t\t\ttimeoutMs: timeoutMs(ready.timeout, 30),\n\t\t\t\t}\n\t\t\t: undefined,\n\t\trestart: params.restart ?? \"no\",","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/hub/launch.ts#L170-L206","documentation":"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).","triggerScenarios":"launch({ op: \"start\", name, application, ready: { port: 0 } }), port: 70000, port: 8080.5, or a string like \"8080\" that is not an integer.","commonSituations":"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.","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."],"exampleFix":"// before\nlaunch({ op: \"start\", name: \"api\", application: \"bun\", ready: { port: \"8080\" } })\n// throws: ready.port must be an integer from 1 to 65535\n\n// after\nlaunch({ op: \"start\", name: \"api\", application: \"bun\", ready: { port: 8080 } })","handlingStrategy":"validation","validationCode":"const port = params.ready?.port;\nif (port !== undefined && (!Number.isInteger(port) || port < 1 || port > 65535)) {\n  throw new Error(\"ready.port must be an integer from 1 to 65535\");\n}","typeGuard":"function isValidPort(p: unknown): p is number {\n  return typeof p === \"number\" && Number.isInteger(p) && p >= 1 && p <= 65535;\n}","tryCatchPattern":"try {\n  await launchTool.run({ op: \"start\", name, application, ready });\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes(\"ready.port must be an integer\")) {\n    // coerce/fix the port and retry\n  } else throw err;\n}","preventionTips":["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."],"tags":["validation","port","tool-args"],"backgroundTag":"invalid-port-range","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}