{"record":{"id":"b83be23cf270f70b","repo":"alibaba/nacos","slug":"at-least-one-protocol-is-required-b83be2","errorCode":null,"errorMessage":"at least one protocol is required","messagePattern":"at least one protocol is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"console-ui-next/src/pages/newAgent/agent-console-model.ts","lineNumber":380,"sourceCode":"  if (!value.trim()) {\n    return undefined;\n  }\n  const parsed = parseJson(value, name);\n  if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {\n    throw new Error(`${name} must be a JSON object`);\n  }\n  return JSON.stringify(parsed);\n}\n\nfunction serializeCallInterfaces(\n  values: AgentEditorValues,\n  protocolEditors?: StructuredProtocolEditorValues[],\n): string {\n  const agentName = required(values.agentName, 'agentName');\n  const version = required(values.version, 'version');\n  if (protocolEditors) {\n    if (protocolEditors.length === 0) {\n      throw new Error('at least one protocol is required');\n    }\n    return JSON.stringify(validateUniqueProtocols(protocolEditors.map(\n      (editor) => buildStructuredCallInterface(agentName, version, editor),\n    )));\n  }\n  if (values.protocolEditorKind !== 'raw') {\n    return JSON.stringify([buildStructuredCallInterface(\n      agentName,\n      version,\n      editorFromValues(values),\n    )]);\n  }\n  const parsed = parseJson(\n    required(values.callInterfaces, 'callInterfaces'),\n    'callInterfaces',\n  );\n  if (!Array.isArray(parsed) || parsed.length === 0) {\n    throw new Error('callInterfaces must be a non-empty JSON array');","sourceCodeStart":362,"sourceCodeEnd":398,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/console-ui-next/src/pages/newAgent/agent-console-model.ts#L362-L398","documentation":"Thrown by serializeCallInterfaces when a protocolEditors array is explicitly provided but is empty. An agent must declare at least one callable interface; an empty list is meaningless. Providing undefined (omitting the argument) is allowed and uses the single-interface path.","triggerScenarios":"The UI passes an empty array as protocolEditors, e.g. the user removed all protocol editor blocks but still submitted the form.","commonSituations":"Dynamic form where the user deletes every protocol row. State initialization bug producing [] instead of undefined.","solutions":["Add at least one protocol editor entry before submitting.","If no protocols are intended, pass undefined (omit protocolEditors) rather than [] — though the single-interface fallback will still apply.","Guard the submit handler to block empty protocol lists in the UI."],"exampleFix":"// before\nserializeCallInterfaces(values, []);\n\n// after\nserializeCallInterfaces(values, [structuredA2aEditor]);  // at least one","handlingStrategy":"validation","validationCode":"function checkProtocolEditors(editors) {\n  if (editors && editors.length === 0) throw new Error('Add at least one protocol');\n}","typeGuard":"function hasAtLeastOne<T>(arr: T[] | undefined): boolean { return Array.isArray(arr) ? arr.length > 0 : true; }","tryCatchPattern":"try { serializeCallInterfaces(values, editors); } catch (e) {\n  if (/at least one protocol is required/.test(e.message)) { toast.error('Add a protocol entry'); }\n}","preventionTips":["Block submit when protocol list is empty","Pass undefined not [] when no editors","Require one protocol in the form"],"tags":["validation","protocol","required","agent"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}