eyaltoledano/claude-task-master · error
INVALID_SUBTASK_ID
INVALID_SUBTASK_ID
Error message
Subtask ID cannot be empty.
What it means
The subtask `id` argument must be a non-empty string. updateSubtaskByIdDirect rejects null, undefined, non-string values, or whitespace-only strings with INVALID_SUBTASK_ID before any storage lookup. In API storage IDs like 'HAM-2611' are valid; in file storage the form 'parentId.subtaskId' (e.g. '5.2') is expected — but either way it must be a non-empty string.
Source
Thrown at mcp-server/src/core/direct-functions/update-subtask-by-id.js:61
if (!tasksJsonPath) {
const errorMessage = 'tasksJsonPath is required but was not provided.';
logWrapper.error(errorMessage);
return {
success: false,
error: { code: 'MISSING_ARGUMENT', message: errorMessage }
};
}
// Basic validation - ID must be present
// In API storage, subtask IDs like "HAM-2611" are valid (no dot required)
// In file storage, subtask IDs must be in format "parentId.subtaskId"
// The core function handles storage-specific validation
if (!id || typeof id !== 'string' || !id.trim()) {
const errorMessage = 'Subtask ID cannot be empty.';
logWrapper.error(errorMessage);
return {
success: false,
error: { code: 'INVALID_SUBTASK_ID', message: errorMessage }
};
}
// At least prompt or metadata is required (validated in MCP tool layer)
if (!prompt && !metadata) {
const errorMessage =
'No prompt or metadata specified. Please provide information to append or metadata to update.';
logWrapper.error(errorMessage);
return {
success: false,
error: { code: 'MISSING_PROMPT', message: errorMessage }
};
}
const subtaskIdStr = String(id).trim();
// Use the provided path
const tasksPath = tasksJsonPath;View on GitHub (pinned to c0c98d367c)
Solutions
- Pass the subtask ID as a string: id: '5.2' (file storage) or the ticket ID like 'HAM-2611' (API storage).
- Verify the value is defined at the call site — log or inspect arguments before the tool call.
- If the ID comes from another tool's output, confirm that lookup succeeded and copy the exact ID.
Example fix
// before const id = 5.2; // number — wrong // after const id = '5.2'; // dotted string
Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof id !== 'string' || !id.trim()) throw new Error('subtask id must be a non-empty string');
// file storage additionally expects 'parentId.subtaskId'
if (/\d+\.\d+/.test(id) === false && !/^[A-Z]+-\d+/.test(id)) {
console.warn('ID does not look like "5.2" or "HAM-2611"');
} Type guard
function isSubtaskId(v) { return typeof v === 'string' && v.trim().length > 0 && (/^\d+\.\d+$/.test(v.trim()) || /^[A-Z]+-\d+(\.\d+)?$/.test(v.trim())); } Prevention
- Always quote dotted subtask IDs — numeric 5.2 loses precision and type
- Copy IDs verbatim from get-tasks output instead of retyping
- Validate IDs with a regex helper before any task/subtask tool call
When it happens
Trigger: Passing id: null/undefined, a number (5.2 as float loses the dotted-string semantics), an empty string, or ' ' when calling the update-subtask-by-id tool.
Common situations: JavaScript callers passing numeric subtask IDs (5.02 collapses to 5.2); template strings interpolating an undefined variable into ''; agents hallucinating an ID after a failed task lookup.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- Generated object does not match schema: ${validationError.me
- MISSING_ARGUMENT
- INPUT_VALIDATION_ERROR
- MISSING_ARGUMENT
- INPUT_VALIDATION_ERROR
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/912275e6c29c02ab.
Report an issue: GitHub.