alibaba/nacos · error · Error

${name} must be a JSON object

Error message

${name} must be a JSON object

What it means

Thrown by serializeOptionalObject when a non-empty JSON value parses to something that is not a plain object — null, an array, or a primitive. The helper is used for optional object-typed fields that may be omitted (empty string = undefined) but, when present, must be an object.

Source

Thrown at console-ui-next/src/pages/newAgent/agent-console-model.ts:367

function validateUniqueProtocols(callInterfaces: AgentCallInterface[]): AgentCallInterface[] {
  const protocols = new Set<string>();
  for (const callInterface of callInterfaces) {
    if (protocols.has(callInterface.protocol)) {
      throw new Error(`protocol must be unique: ${callInterface.protocol}`);
    }
    protocols.add(callInterface.protocol);
  }
  return callInterfaces;
}

function serializeOptionalObject(value: string, name: string): string | undefined {
  if (!value.trim()) {
    return undefined;
  }
  const parsed = parseJson(value, name);
  if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
    throw new Error(`${name} must be a JSON object`);
  }
  return JSON.stringify(parsed);
}

function serializeCallInterfaces(
  values: AgentEditorValues,
  protocolEditors?: StructuredProtocolEditorValues[],
): string {
  const agentName = required(values.agentName, 'agentName');
  const version = required(values.version, 'version');
  if (protocolEditors) {
    if (protocolEditors.length === 0) {
      throw new Error('at least one protocol is required');
    }
    return JSON.stringify(validateUniqueProtocols(protocolEditors.map(
      (editor) => buildStructuredCallInterface(agentName, version, editor),
    )));
  }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Provide a JSON object {"key":"value"} or leave the field empty to omit it.
  2. Convert arrays to keyed objects if the schema requires an object.
  3. Validate the parsed type before submit.

Example fix

// before
["read","write"]

// after
{"scope1":"read","scope2":"write"}  // or leave empty to omit
Defensive patterns

Strategy: type-guard

Validate before calling

function checkOptionalObject(text, name) {
  if (!text.trim()) return undefined;
  const parsed = JSON.parse(text);
  if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') throw new Error(`${name} must be an object`);
  return parsed;
}

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> {
  return v !== null && !Array.isArray(v) && typeof v === 'object';
}

Try / catch

try { serializeOptionalObject(text, name); } catch (e) {
  if (/must be a JSON object/.test(e.message)) { toast.error(`${name} must be an object`); }
}

Prevention

When it happens

Trigger: User enters an array or null or a number in an optional object field (e.g. capabilities, securitySchemes) instead of a key-value object.

Common situations: Field accepts a JSON object but user provides a JSON array. Placeholder defaults to 'null'. Misreading the field as a list.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/b813e40334feccd6. Report an issue: GitHub.