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

  1. Run `crabbox inspect --provider <p> --id <id> --json | jq .sshFallbackPorts` and confirm it is a JSON array.
  2. Align the Crabbox binary version with this provider's expected inspect contract (array of integers).
  3. If the provider genuinely exposes a single fallback, ensure it still serializes as a one-element array.
  4. 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

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


AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12). Data as JSON: /api/errors/dc48f7bfe145401e. Report an issue: GitHub.