{"record":{"id":"7d788cf4137badfd","repo":"alibaba/spring-ai-alibaba","slug":"invalid-dsl","errorCode":null,"errorMessage":"invalid dsl","messagePattern":"invalid dsl","errorType":"validation","errorClass":"IllegalArgumentException","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/dsl/adapters/CustomDSLAdapter.java","lineNumber":151,"sourceCode":"\t}\n\n\t// TODO\n\t@Override\n\tpublic ChatBot mapToChatBot(Map<String, Object> data) {\n\t\treturn null;\n\t}\n\n\t// TODO\n\t@Override\n\tpublic Map<String, Object> chatbotToMap(ChatBot chatBot) {\n\t\treturn null;\n\t}\n\n\t@Override\n\tpublic void validateDSLData(Map<String, Object> data) {\n\t\tMap<String, Object> metadataMap = (Map<String, Object>) data.get(\"metadata\");\n\t\tif (metadataMap == null || !metadataMap.containsKey(\"mode\")) {\n\t\t\tthrow new IllegalArgumentException(\"invalid dsl\");\n\t\t}\n\t}\n\n\t@Override\n\tpublic Serializer getSerializer() {\n\t\treturn serializer;\n\t}\n\n\t@Override\n\tpublic Boolean supportDialect(DSLDialectType dialectType) {\n\t\treturn DSLDialectType.CUSTOM.equals(dialectType);\n\t}\n\n}\n","sourceCodeStart":133,"sourceCodeEnd":166,"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/dsl/adapters/CustomDSLAdapter.java#L133-L166","documentation":"Thrown by CustomDSLAdapter.validateDSLData when the DSL map has no 'metadata' object or the metadata map lacks a 'mode' key. Custom DSL imports must declare their mode in metadata so the adapter knows how to interpret the rest of the document. The message is intentionally terse.","triggerScenarios":"Calling validateDSLData or importDSL with a map where data.get(\"metadata\") is null; metadata exists but contains no 'mode' key; hand-built maps passed directly to the custom adapter.","commonSituations":"Building a custom DSL map programmatically and forgetting the metadata block; copying only the node/edge portion of an export; stripping metadata during preprocessing; using the generic adapter on a DSL that belongs to Agent/Dify/Studio adapters.","solutions":["Add a metadata object containing at least a 'mode' key: {\"metadata\": {\"mode\": \"...\"}}","Set mode to the value expected by your custom app (e.g. chatbot/workflow as defined by AppMetadata constants)","Re-export the DSL from the Studio UI so metadata is included","Ensure you are using the adapter that matches your DSL format"],"exampleFix":"// before\ndslData.put(\"nodes\", nodes);\n\n// after\ndslData.put(\"metadata\", Map.of(\"mode\", \"workflow\"));\ndslData.put(\"nodes\", nodes);","handlingStrategy":"validation","validationCode":"Object meta = data.get(\"metadata\");\nif (!(meta instanceof Map) || !((Map<?, ?>) meta).containsKey(\"mode\")) {\n    throw new IllegalArgumentException(\"custom DSL requires metadata.mode\");\n}","typeGuard":"boolean hasMetadataMode(Map<String,Object> data) { return data.get(\"metadata\") instanceof Map<?,?> m && m.containsKey(\"mode\"); }","tryCatchPattern":"try { customAdapter.validateDSLData(data); } catch (IllegalArgumentException e) { log.warn(\"Custom DSL rejected: metadata/mode missing\"); throw e; }","preventionTips":["Always include a metadata block with a 'mode' key when constructing custom DSL maps","Re-export from the UI rather than assembling DSL fragments manually","Don't feed non-custom DSL formats to CustomDSLAdapter"],"tags":["dsl","validation","metadata"],"backgroundTag":"missing-required-config-field","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"}