eyaltoledano/claude-task-master · error
AI service did not return a valid task object.
Error message
AI service did not return a valid task object.
What it means
Even when the AI service responds with a mainResult, addTask() requires the unwrapped object (mainResult itself, or mainResult.object) to contain title and description fields, since that object becomes taskData. If neither location yields a valid task object, it throws rather than persisting a broken task.
Source
Thrown at scripts/modules/task-manager/add-task.js:461
throw new Error(
'AI service did not return the expected object structure.'
);
}
// Prefer mainResult if it looks like a valid task object, otherwise try mainResult.object
if (
aiServiceResponse.mainResult.title &&
aiServiceResponse.mainResult.description
) {
taskData = aiServiceResponse.mainResult;
} else if (
aiServiceResponse.mainResult.object &&
aiServiceResponse.mainResult.object.title &&
aiServiceResponse.mainResult.object.description
) {
taskData = aiServiceResponse.mainResult.object;
} else {
throw new Error('AI service did not return a valid task object.');
}
report('Successfully generated task data from AI.', 'success');
// Success! Show checkmark
if (loadingIndicator) {
succeedLoadingIndicator(
loadingIndicator,
'Task generated successfully'
);
loadingIndicator = null; // Clear it
}
} catch (error) {
// Failure! Show X
if (loadingIndicator) {
failLoadingIndicator(loadingIndicator, 'AI generation failed');
loadingIndicator = null;
}View on GitHub (pinned to c0c98d367c)
Solutions
- Retry generation, optionally with a more schema-compliant model, since this is usually malformed model output.
- Check the zod task schema in generateObjectService — ensure it requires title and description so invalid output is rejected/retried upstream.
- Fall back to manual add-task with explicit title and description arguments.
Example fix
// before
const data = await generateObjectService(...); // schema allows optional title
// after
const data = await generateObjectService(...); // schema: z.object({ title: z.string().min(1), description: z.string().min(1) }) Defensive patterns
Strategy: type-guard
Type guard
function isValidTaskObject(res) {
const o = res?.mainResult?.object ?? res?.mainResult;
return !!o && typeof o === 'object' && typeof o.title === 'string' && o.title.length > 0 && typeof o.description === 'string' && o.description.length > 0;
} Try / catch
try {
await addTask(tasksPath, { prompt });
} catch (err) {
if (err.message.includes('did not return a valid task object')) {
// retry once, then fall back to manual entry
await addTask(tasksPath, { taskData: { title: manualTitle, description: manualDescription } });
} else throw err;
} Prevention
- Use models known to follow JSON schemas for task generation.
- Enforce strict zod schemas (title/description required) in the generation service.
- Retry generation automatically on schema mismatch before giving up.
When it happens
Trigger: generateObjectService returns { mainResult } but mainResult lacks title/description (e.g. it's an array, a validation-error stub, or the object is nested under a different key not named 'object').
Common situations: Model output that fails zod schema validation and is returned partially; provider returning a different schema after a model change; using a model that ignores the requested JSON schema and returns prose or a wrapped envelope.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- AI service did not return the expected object structure.
- AI response did not include a valid subtasks array.
- Schema validation failed: ${errors}
- Manual task data must include at least a title and descripti
- Warning: Invalid Claude Code settings in config: ${error.mes
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/15d90f6d174372d5.
Report an issue: GitHub.