alibaba/nacos · error · Error
agentCard must be a JSON object
Error message
agentCard must be a JSON object
What it means
Thrown by normalizeA2aAgentCard after parsing the agentCard JSON text: the parsed value is not a plain object (it is an array, primitive, or null). The AgentCard must be a top-level JSON object so its fields (name, version, supportedInterfaces) can be read.
Source
Thrown at console-ui-next/src/pages/newAgent/agent-console-model.ts:234
'AgentCard interface protocolVersion',
);
return {
...value,
url,
transport: protocolBinding,
protocolBinding,
protocolVersion,
};
}
function normalizeA2aAgentCard(
agentName: string,
version: string,
text: string,
): { card: Record<string, unknown>; declaredEndpoints: AgentCallInterface['declaredEndpoints'] } {
const parsed = parseAgentCardJson(required(text, 'agentCard'));
if (!isObject(parsed)) {
throw new Error('agentCard must be a JSON object');
}
const card: Record<string, unknown> = { ...parsed, name: agentName, version };
const topProtocolVersion = optionalString(card.protocolVersion);
const preferredTransport = optionalString(card.preferredTransport);
let interfaces: Record<string, unknown>[];
if (Array.isArray(card.supportedInterfaces) && card.supportedInterfaces.length > 0) {
interfaces = card.supportedInterfaces.map((item) => normalizeA2aInterface(
item,
preferredTransport,
topProtocolVersion,
));
} else {
const preferred = normalizeA2aInterface({
url: card.url,
protocolBinding: preferredTransport,
protocolVersion: topProtocolVersion,
});
interfaces = [preferred];View on GitHub (pinned to 9b989acdf1)
Solutions
- Provide a full AgentCard object with top-level fields, not an array.
- Wrap a bare array in an object: {"supportedInterfaces":[...],"name":"...","version":"..."}.
- Validate the root type is an object before submit.
Example fix
// before
[{"url":"https://a.example.com","transport":"GRPC"}]
// after
{"name":"my-agent","version":"1.0.0","supportedInterfaces":[{"url":"https://a.example.com","transport":"GRPC"}]} Defensive patterns
Strategy: type-guard
Validate before calling
function checkAgentCard(parsed) { if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') throw new Error('agentCard must be an object'); } Type guard
function isAgentCardObject(v: unknown): v is Record<string, unknown> {
return v !== null && !Array.isArray(v) && typeof v === 'object';
} Try / catch
try { normalizeA2aAgentCard(name, ver, text); } catch (e) {
if (/agentCard must be a JSON object/.test(e.message)) { toast.error('Wrap the card in a JSON object'); }
} Prevention
- Wrap card fields in a top-level object
- Validate root type before submit
- Use the structured editor for AgentCard
When it happens
Trigger: User enters a JSON array '[...]' or a bare string/number as the agentCard, or 'null'. parseAgentCardJson succeeds but the result is non-object.
Common situations: User wraps the card in an array by mistake. User pastes only the supportedInterfaces array thinking it is the whole card.
Related errors
- AgentCard interface must be a JSON object
- 20002
- PARAMETER_MISSING
- INVALID_PARAM
- Legacy A2A Endpoint address must not be empty
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/51d82e00ffb36694.
Report an issue: GitHub.