{"record":{"id":"dc48f7bfe145401e","repo":"openclaw/openclaw","slug":"crabbox-inspect-returned-invalid-sshfallbackports","errorCode":null,"errorMessage":"Crabbox inspect returned invalid sshFallbackPorts","messagePattern":"Crabbox inspect returned invalid sshFallbackPorts","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extensions/crabbox/src/crabbox-worker-inspect.ts","lineNumber":124,"sourceCode":"  if (typeof value !== \"string\") {\n    throw new Error(`Crabbox inspect returned an invalid ${field}`);\n  }\n  return nonEmptyString(value);\n}\n\nfunction inspectPort(value: unknown): number | undefined {\n  if (value === undefined || value === \"\") {\n    return undefined;\n  }\n  return inspectRequiredPort(value, \"sshPort\");\n}\n\nfunction inspectFallbackPorts(value: unknown, primaryPort: number | undefined): number[] {\n  if (value === undefined) {\n    return [];\n  }\n  if (!Array.isArray(value)) {\n    throw new Error(\"Crabbox inspect returned invalid sshFallbackPorts\");\n  }\n  const seen = new Set(primaryPort === undefined ? [] : [primaryPort]);\n  const ports: number[] = [];\n  for (const entry of value) {\n    const port = inspectRequiredPort(entry, \"sshFallbackPorts\");\n    if (!seen.has(port)) {\n      seen.add(port);\n      ports.push(port);\n    }\n  }\n  if (ports.length > MAX_SSH_FALLBACK_PORTS) {\n    throw new Error(\"Crabbox inspect returned invalid sshFallbackPorts: maximum 10\");\n  }\n  return ports;\n}\n\nfunction inspectRequiredPort(value: unknown, field: \"sshPort\" | \"sshFallbackPorts\"): number {\n  if (typeof value !== \"number\" && (typeof value !== \"string\" || !/^\\d+$/u.test(value))) {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/crabbox/src/crabbox-worker-inspect.ts#L106-L142","documentation":"Thrown by inspectFallbackPorts() when the Crabbox inspect JSON contains an sshFallbackPorts field that is defined (not undefined) but is not a JSON array. The provider requires fallback ports to be a list of port numbers; any other shape (string, number, object) is rejected as malformed lease metadata.","triggerScenarios":"parseInspectJson processes an inspect payload where sshFallbackPorts is a scalar (e.g. \"22,2222\" as a comma-separated string, or 22 as a single number) rather than [22, 2222]. Occurs at crabbox-worker-inspect.ts:86 via inspectFallbackPorts.","commonSituations":"Crabbox binary version that serializes fallback ports as a delimited string instead of an array; a custom provider plugin emitting the wrong shape; hand-edited or mocked inspect JSON used in tests that used a string instead of an array.","solutions":["Run `crabbox inspect --provider <p> --id <id> --json | jq .sshFallbackPorts` and confirm it is a JSON array.","Align the Crabbox binary version with this provider's expected inspect contract (array of integers).","If the provider genuinely exposes a single fallback, ensure it still serializes as a one-element array.","Stop and re-provision: `crabbox stop --provider <p> --id <id>` then retry provision."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isPortArray(value: unknown): value is unknown[] {\n  return Array.isArray(value);\n}","tryCatchPattern":"try {\n  await provider.provision(profile, operationId);\n} catch (error) {\n  if (error instanceof Error && error.message.includes(\"invalid sshFallbackPorts\")) {\n    // sshFallbackPorts was present but not an array — re-provision after fixing the Crabbox provider\n  }\n  throw error;\n}","preventionTips":["Ensure Crabbox provider plugins emit sshFallbackPorts as a JSON array of integers (or omit it).","Do not serialize fallback ports as a delimited string.","Pin the Crabbox binary version; inspect contract changes are a common cause."],"tags":["crabbox","worker-provider","validation","json-parsing","ssh","ports"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}