openclaw/openclaw · error · Error

Buzz QA credentials are missing or malformed.

Error message

Buzz QA credentials are missing or malformed.

What it means

Thrown by parseBuzzQaCredentialPayload when the Zod strict-object schema validation (safeParse) fails on the credential payload. The schema requires relayUrl (safe URL), roomId (non-empty), driverPrivateKey (non-empty), sutPrivateKey (non-empty), optional driverAuthTag and sutAuthTag, and rejects unknown keys due to .strict(). This is the primary credential validation entry point used by both file and convex credential sources.

Source

Thrown at extensions/buzz/src/qa/credentials.ts:42

    // stay on loopback and never cross a network boundary.
    relayUrl: z.string().url().refine(isSafeBuzzQaRelayUrl),
    roomId: z.string().min(1),
    driverPrivateKey: z.string().min(1),
    sutPrivateKey: z.string().min(1),
    driverAuthTag: z.string().optional(),
    sutAuthTag: z.string().optional(),
  })
  .strict();

export type BuzzQaCredentials = z.output<typeof buzzQaCredentialPayloadSchema> & {
  driverPublicKey: string;
  sutPublicKey: string;
};

export function parseBuzzQaCredentialPayload(payload: unknown): BuzzQaCredentials {
  const parsed = buzzQaCredentialPayloadSchema.safeParse(payload);
  if (!parsed.success) {
    throw new Error("Buzz QA credentials are missing or malformed.");
  }
  let roomId: string;
  let driverPublicKey: string;
  let sutPublicKey: string;
  try {
    roomId = parseBuzzTarget(parsed.data.roomId);
    driverPublicKey = resolveBuzzPublicKey(parsed.data.driverPrivateKey);
    sutPublicKey = resolveBuzzPublicKey(parsed.data.sutPrivateKey);
    parseBuzzAuthTag(parsed.data.driverAuthTag ?? "");
    parseBuzzAuthTag(parsed.data.sutAuthTag ?? "");
  } catch {
    throw new Error("Buzz QA credentials are missing or malformed.");
  }
  if (driverPublicKey === sutPublicKey) {
    throw new Error("Buzz QA requires distinct driver and SUT identities.");
  }
  return {
    ...parsed.data,

View on GitHub (pinned to 01804a7531)

Solutions

  1. Ensure the JSON has all required fields: relayUrl, roomId, driverPrivateKey, sutPrivateKey.
  2. Remove any fields not in the schema (the schema is strict).
  3. Verify relayUrl uses wss: (or ws: only for 127.0.0.1/localhost/[::1]).
  4. Run the JSON through a validator or compare against a known-good credential file.

Example fix

// before
{ "relayUrl": "http://relay.example.com", "roomId": "...", "driverPrivateKey": "...", "sutPrivateKey": "..." }
// after
{ "relayUrl": "wss://relay.example.com", "roomId": "...", "driverPrivateKey": "...", "sutPrivateKey": "..." }
Defensive patterns

Strategy: validation

Validate before calling

import { z } from 'zod';
import { isLoopbackHost } from 'openclaw/plugin-sdk/ssrf-runtime';

const schema = z.object({
  relayUrl: z.string().url().refine((v) => {
    const u = new URL(v);
    return u.protocol === 'wss:' || (u.protocol === 'ws:' && isLoopbackHost(u.hostname));
  }),
  roomId: z.string().min(1),
  driverPrivateKey: z.string().min(1),
  sutPrivateKey: z.string().min(1),
  driverAuthTag: z.string().optional(),
  sutAuthTag: z.string().optional(),
}).strict();

const result = schema.safeParse(rawPayload);
if (!result.success) {
  console.error('Schema errors:', result.error.issues);
}

Prevention

When it happens

Trigger: Missing a required field (relayUrl, roomId, driverPrivateKey, or sutPrivateKey); including an unknown key like 'extra'; relayUrl is not a valid URL or fails the SSRF-safe refine check (must be wss: or loopback ws:); passing a non-object payload.

Common situations: Hand-editing a credential JSON and dropping a field; typo in a key name; using http: relay URL instead of wss:; using ws: to a non-loopback host.

Understand the failure class

Related errors


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