{"record":{"id":"9a6039b08296ed6b","repo":"conductor-oss/conductor","slug":"error-preparing-chat-completion-task-input-s-9a6039","errorCode":null,"errorMessage":"Error preparing chat completion task input: %s","messagePattern":"Error preparing chat completion task input: (.+?)","errorType":"exception","errorClass":"TerminateWorkflowException","httpStatus":null,"severity":"critical","filePath":"ai/src/main/java/org/conductoross/conductor/ai/tasks/mapper/ChatCompleteTaskMapper.java","lineNumber":104,"sourceCode":"                history.add(new ChatMessage(ChatMessage.Role.user, chatCompletion.getUserInput()));\n            }\n            // getHistory() internally skips prior loop-iteration assistant messages\n            // for this same task refName when (a) previousResponseId is in play\n            // (OpenAI Responses API server-side store owns the prior turns) or\n            // (b) the provider declares it doesn't accept assistant-message\n            // prefill (AIModel.supportsAssistantPrefill — e.g. Anthropic, where\n            // Claude Sonnet 4.6+ rejects prefill outright). Participants, tool\n            // calls, and sub-workflow context are still preserved in both cases.\n            getHistory(workflowModel, taskModel, chatCompletion);\n            updateTaskModel(chatCompletion, taskModel);\n\n        } catch (Exception e) {\n            if (e instanceof TerminateWorkflowException) {\n                throw (TerminateWorkflowException) e;\n            } else {\n                log.error(\"input: {}\", taskModel.getInputData());\n                log.error(e.getMessage(), e);\n                throw new TerminateWorkflowException(\n                        String.format(\n                                \"Error preparing chat completion task input: %s\", e.getMessage()));\n            }\n        }\n        return taskModel;\n    }\n\n    protected void updateTaskModel(ChatCompletion chatCompletion, TaskModel simpleTask) {\n        Map<String, Object> paramReplacement = chatCompletion.getPromptVariables();\n        if (paramReplacement == null) {\n            paramReplacement = new HashMap<>();\n        }\n        List<ChatMessage> messages = chatCompletion.getMessages();\n        if (messages == null) {\n            messages = new ArrayList<>();\n        }\n        for (ChatMessage message : messages) {\n            String msgText = message.getMessage();","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/tasks/mapper/ChatCompleteTaskMapper.java#L86-L122","documentation":"Thrown by ChatCompleteTaskMapper.getMappedTask as a TerminateWorkflowException when any exception occurs while preparing a chat completion task's input (JSON conversion of inputData to ChatCompletion, history collection, or template substitution). It re-throws pre-existing TerminateWorkflowExceptions unchanged but wraps all other exceptions, logging the raw inputData and stack trace first. This terminates the entire workflow, not just the task.","triggerScenarios":"taskModel.getInputData() cannot be converted to ChatCompletion (Jackson mismatch/missing required field), an NPE during getHistory (e.g. a task with null WorkflowTask or missing taskReferenceName), or a StringTemplate.fString failure on a ${...} variable with no replacement value.","commonSituations":"A workflow author provides chat-complete task input with the wrong shape (missing 'messages'/'userInput'), references a participant/tool taskRefName that does not exist, uses a ${variable} with no promptVariables mapping, or a prior task output that cannot be coerced into LLMResponse.","solutions":["Read the two log.error lines emitted before the throw: the first dumps the full inputData, the second the root exception + stack trace.","Validate the chat-complete task input schema (model, messages/userInput, llmProvider) against ChatCompletion.","Ensure every ${...} placeholder in messages has a matching key in promptVariables.","Confirm referenced participant/tool taskRefNames exist earlier in the workflow.","Wrap risky upstream tasks so their output is always mappable to LLMResponse."],"exampleFix":"// before (workflow input missing required fields)\n{\n  \"llmProvider\": \"openai\",\n  \"model\": \"gpt-4o\"\n  // missing messages / userInput -> Jackson/NullPointerException\n}\n\n// after\n{\n  \"llmProvider\": \"openai\",\n  \"model\": \"gpt-4o\",\n  \"userInput\": \"Summarize the report\",\n  \"promptVariables\": {\"topic\": \"sales\"}\n}","handlingStrategy":"validation","validationCode":"Object input = taskModel.getInputData();\nif (input == null || (!(input instanceof Map) && !(input instanceof ChatCompletion))) {\n    throw new IllegalArgumentException(\"chat-complete task input is missing or wrong type\");\n}\n// Ensure at least one prompt source is present\nMap<?,?> map = (Map<?,?>) input;\nif (!map.containsKey(\"messages\") && !map.containsKey(\"userInput\")) {\n    throw new IllegalArgumentException(\"chat-complete task requires 'messages' or 'userInput'\");\n}","typeGuard":null,"tryCatchPattern":"// TerminateWorkflowException is not catchable in user code (engine-level);\n// prevent it by validating input before the mapper runs.\n// In a worker, surface mapping failures via task output instead.\ntry {\n    objectMapper.convertValue(inputData, ChatCompletion.class);\n} catch (IllegalArgumentException e) {\n    // fix the input shape before the task is scheduled","preventionTips":["Validate chat-complete task input schema before running the workflow.","Provide a promptVariables entry for every ${...} placeholder used in messages.","Ensure referenced participant/tool taskRefNames exist earlier in the workflow.","Read the two log.error lines emitted by the mapper to find the root cause.","Make upstream task outputs always mappable to LLMResponse (include a 'result' field)."],"tags":["conductor","task-mapper","chat-completion","workflow-termination","jackson","template"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}