{"record":{"id":"1191c22c6cdf54ff","repo":"alibaba/spring-ai-alibaba","slug":"invalid-output","errorCode":null,"errorMessage":"invalid output","messagePattern":"invalid output","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/builder/generator/service/generator/workflow/sections/QuestionClassifierNodeSection.java","lineNumber":68,"sourceCode":"\t\t\t\t\"\"\", node.getId(), varName, ObjectToCodeUtil.toCode(nodeData.getChatModeName()),\n\t\t\t\tObjectToCodeUtil.toCode(nodeData.getModeParams()), nodeData.getInputSelector().getNameInCode(),\n\t\t\t\tnodeData.getOutputKey(),\n\t\t\t\tObjectToCodeUtil.toCode(nodeData.getClasses()\n\t\t\t\t\t.stream()\n\t\t\t\t\t.collect(Collectors.toUnmodifiableMap(QuestionClassifierNodeData.ClassConfig::id,\n\t\t\t\t\t\t\tQuestionClassifierNodeData.ClassConfig::classTemplate, (a, b) -> b))),\n\t\t\t\tObjectToCodeUtil.toCode(List.of(nodeData.getPromptTemplate())));\n\t}\n\n\t@Override\n\tpublic String renderEdges(QuestionClassifierNodeData nodeData, List<Edge> edges) {\n\t\tMap<String, String> classIdToName = nodeData.getClassIdToName();\n\t\t// 规定edge的sourceHandle为caseId，前面的转化需要符合这条规则\n\t\tString edgeCode = String.format(\"\"\"\n\t\t\t\tstate -> {\n\t\t\t\t    String result = state.value(\"%s\").orElseThrow().toString();\n\t\t\t\t    %s\n\t\t\t\t    throw new RuntimeException(\"invalid output\");\n\t\t\t\t}\n\t\t\t\t\"\"\", nodeData.getOutputKey(),\n\t\t\t\tnodeData.getClasses()\n\t\t\t\t\t.stream()\n\t\t\t\t\t.map(QuestionClassifierNodeData.ClassConfig::id)\n\t\t\t\t\t.map(id -> String.format(\"\"\"\n\t\t\t\t\t\t\tif(\"%s\".equals(result)) {\n\t\t\t\t\t\t\t    return \"%s\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\"\"\", id, classIdToName.getOrDefault(id, id)))\n\t\t\t\t\t.collect(Collectors.joining(\"\\n\")));\n\n\t\tMap<String, String> caseToTarget = edges.stream()\n\t\t\t.collect(Collectors.toUnmodifiableMap(\n\t\t\t\t\te -> classIdToName.getOrDefault(e.getSourceHandle(), e.getSourceHandle()), Edge::getTarget));\n\n\t\treturn String.format(\"\"\"\n\t\t\t\t// render QuestionNode [%s]'s edge","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/builder/generator/service/generator/workflow/sections/QuestionClassifierNodeSection.java#L50-L86","documentation":"QuestionClassifierNodeSection.renderEdges generates an edge lambda that reads the classifier's output key and maps the classification id to the next node. If the value matches none of the known class ids, the generated code throws RuntimeException(\"invalid output\") as a final fallback.","triggerScenarios":"At runtime, state.value(outputKey) contains a string that is not one of the nodeData class ids — e.g., the classifier LLM returned text that mapped to an unexpected/normalized id, or outputKey was overwritten by another node.","commonSituations":"Classifier model output not matching any configured class label; class ids changed in the DSL after edges were generated; two nodes writing to the same output key; model returning empty/garbage classification.","solutions":["Verify the classifier classes' ids/labels match what the classification prompt produces","Ensure outputKey is unique and written only by the classifier node","Add a default/fallback class so every model response maps to a known id","Check prompt template constraints so the model outputs exactly one class label"],"exampleFix":"// before\nclasses: [A, B] // model returns \"C\"\n// after\nclasses: [A, B, {id:\"other\", label:\"fallback\"}]","handlingStrategy":"try-catch","validationCode":"String out = state.value(outputKey).orElse(\"\"); if (classes.stream().noneMatch(c -> c.id().equals(out))) { log.warn(\"Classifier output not a known class id: {}\", out); }","typeGuard":"null","tryCatchPattern":"try { edgeFunction.apply(state); } catch (RuntimeException e) { routeToFallbackNode(state); }","preventionTips":["Constrain the classifier prompt to output exactly one configured label","Always configure a fallback class","Keep class ids stable across DSL edits","Give the classifier output key a dedicated state field"],"tags":["java","workflow","classification","mapping"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}