{"record":{"id":"5ccec2de7b9b8bde","repo":"conductor-oss/conductor","slug":"model-string-cannot-be-null-or-empty","errorCode":null,"errorMessage":"Model string cannot be null or empty","messagePattern":"Model string cannot be null or empty","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"common/src/main/java/org/conductoross/conductor/common/metadata/agent/ModelParser.java","lineNumber":40,"sourceCode":"public class ModelParser {\n\n    @Data\n    @AllArgsConstructor\n    public static class ParsedModel {\n        private String provider;\n        private String model;\n    }\n\n    /**\n     * Parse a model string like \"openai/gpt-4o\" into provider and model.\n     *\n     * @param modelString The model string in \"provider/model\" format.\n     * @return A ParsedModel with provider and model components.\n     * @throws IllegalArgumentException if the format is invalid.\n     */\n    public static ParsedModel parse(String modelString) {\n        if (modelString == null || modelString.isBlank()) {\n            throw new IllegalArgumentException(\"Model string cannot be null or empty\");\n        }\n\n        int slashIdx = modelString.indexOf('/');\n        if (slashIdx <= 0 || slashIdx >= modelString.length() - 1) {\n            throw new IllegalArgumentException(\n                    \"Invalid model format: '\" + modelString + \"'. Expected 'provider/model'.\");\n        }\n\n        String provider = modelString.substring(0, slashIdx);\n        String model = modelString.substring(slashIdx + 1);\n        return new ParsedModel(provider, model);\n    }\n}\n","sourceCodeStart":22,"sourceCodeEnd":54,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/common/src/main/java/org/conductoross/conductor/common/metadata/agent/ModelParser.java#L22-L54","documentation":"ModelParser.parse rejects a null or blank model string outright. The parser expects a 'provider/model' formatted identifier and fails fast before any splitting when the input is absent or whitespace-only. Mirrors the Python model_parser.","triggerScenarios":"Calling ModelParser.parse(null) or ModelParser.parse(\"\") / parse(\"   \") from agent/AI-task configuration resolution.","commonSituations":"An agent task definition with a missing or empty 'model' field; a config default that resolves to null; environment variable for the model not set.","solutions":["Provide a non-empty model string in 'provider/model' form (e.g. 'openai/gpt-4o').","Validate/require the model config field at agent-definition load time.","Fall back to a documented default model when the configured value is absent."],"exampleFix":"// before: null/blank model throws\nParsedModel m = ModelParser.parse(agent.getModel());\n\n// after: guard then default\nString model = agent.getModel();\nif (model == null || model.isBlank()) {\n    model = DEFAULT_MODEL; // e.g. \"openai/gpt-4o\"\n}\nParsedModel m = ModelParser.parse(model);","handlingStrategy":"validation","validationCode":"// Guard against null/blank before parsing\nstatic boolean isNonBlankModel(String s) {\n    return s != null && !s.isBlank();\n}\nif (!isNonBlankModel(modelString)) {\n    throw new IllegalArgumentException(\"model must be a non-empty 'provider/model' string\");\n}","typeGuard":"// Narrow to a present, non-blank model string\nstatic boolean isParsableModelString(String s) {\n    return s != null && !s.isBlank()\n        && s.indexOf('/') > 0 && s.indexOf('/') < s.length() - 1;\n}","tryCatchPattern":"// Catch missing model and apply a default\ntry {\n    return ModelParser.parse(modelString);\n} catch (IllegalArgumentException e) {\n    return ModelParser.parse(DEFAULT_MODEL);\n}","preventionTips":["Require a non-empty 'model' field in agent definitions.","Apply a documented default model when the configured value is absent.","Validate model config at agent-definition load time."],"tags":["agent","model-parser","validation","input"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}