openclaw/openclaw · error
Crabbox inspect returned invalid sshFallbackPorts
Error message
Crabbox inspect returned invalid sshFallbackPorts
What it means
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.
Source
Thrown at extensions/crabbox/src/crabbox-worker-inspect.ts:124
if (typeof value !== "string") {
throw new Error(`Crabbox inspect returned an invalid ${field}`);
}
return nonEmptyString(value);
}
function inspectPort(value: unknown): number | undefined {
if (value === undefined || value === "") {
return undefined;
}
return inspectRequiredPort(value, "sshPort");
}
function inspectFallbackPorts(value: unknown, primaryPort: number | undefined): number[] {
if (value === undefined) {
return [];
}
if (!Array.isArray(value)) {
throw new Error("Crabbox inspect returned invalid sshFallbackPorts");
}
const seen = new Set(primaryPort === undefined ? [] : [primaryPort]);
const ports: number[] = [];
for (const entry of value) {
const port = inspectRequiredPort(entry, "sshFallbackPorts");
if (!seen.has(port)) {
seen.add(port);
ports.push(port);
}
}
if (ports.length > MAX_SSH_FALLBACK_PORTS) {
throw new Error("Crabbox inspect returned invalid sshFallbackPorts: maximum 10");
}
return ports;
}
function inspectRequiredPort(value: unknown, field: "sshPort" | "sshFallbackPorts"): number {
if (typeof value !== "number" && (typeof value !== "string" || !/^\d+$/u.test(value))) {View on GitHub (pinned to 01804a7531)
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.
Defensive patterns
Strategy: try-catch
Type guard
function isPortArray(value: unknown): value is unknown[] {
return Array.isArray(value);
} Try / catch
try {
await provider.provision(profile, operationId);
} catch (error) {
if (error instanceof Error && error.message.includes("invalid sshFallbackPorts")) {
// sshFallbackPorts was present but not an array — re-provision after fixing the Crabbox provider
}
throw error;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Crabbox inspect returned an invalid ${field}
- Crabbox inspect returned invalid sshFallbackPorts: maximum 1
- Crabbox inspect returned an invalid desktop SSH user
- Crabbox config show returned invalid JSON
- Crabbox config show returned an invalid AWS instance profile
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/dc48f7bfe145401e.
Report an issue: GitHub.