eyaltoledano/claude-task-master · error

tagObj must be a valid object

Error message

tagObj must be a valid object

What it means

ensureTagMetadata() validates that its first argument is a non-null object before attaching metadata like 'updated' timestamps to a tag. This library throws when tagObj is null, undefined, or a non-object (string, number, etc.), because the function mutates and returns the tag object and cannot operate on anything else.

Source

Thrown at scripts/modules/utils.js:1910

				});
			}
		}
	}

	return flattened;
}

/**
 * Ensures the tag object has a metadata object with created/updated timestamps.
 * @param {Object} tagObj - The tag object (e.g., data['master'])
 * @param {Object} [opts] - Optional fields (e.g., description, skipUpdate)
 * @param {string} [opts.description] - Description for the tag
 * @param {boolean} [opts.skipUpdate] - If true, don't update the 'updated' timestamp
 * @returns {Object} The updated tag object (for chaining)
 */
function ensureTagMetadata(tagObj, opts = {}) {
	if (!tagObj || typeof tagObj !== 'object') {
		throw new Error('tagObj must be a valid object');
	}

	const now = new Date().toISOString();

	if (!tagObj.metadata) {
		// Create new metadata object
		tagObj.metadata = {
			created: now,
			updated: now,
			...(opts.description ? { description: opts.description } : {})
		};
	} else {
		// Ensure existing metadata has required fields
		if (!tagObj.metadata.created) {
			tagObj.metadata.created = now;
		}

		// Update timestamp unless explicitly skipped

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Confirm the variable passed is the tag object, not the tag name string
  2. Check that the tag exists before calling: const tag = data.tags[tag]; if (!tag) create it first
  3. Add a guard before the call: if (tag && typeof tag === 'object') ensureTagMetadata(tag, opts)
  4. Log the value and its typeof to find where it became null/undefined

Example fix

// before
ensureTagMetadata(data.tags[tagName], { description: 'My tag' });
// after
if (!data.tags[tagName]) throw new Error(`Tag '${tagName}' not found`);
ensureTagMetadata(data.tags[tagName], { description: 'My tag' });
Defensive patterns

Strategy: validation

Validate before calling

if (!tagObj || typeof tagObj !== 'object') {
  throw new TypeError(`ensureTagMetadata expects an object, got ${tagObj === null ? 'null' : typeof tagObj}`);
}
ensureTagMetadata(tagObj, { skipUpdate: true });

Type guard

function isTagObject(v) {
  return v !== null && typeof v === 'object' && typeof v.name === 'string';
}

Try / catch

try {
  ensureTagMetadata(tagObj, opts);
} catch (err) {
  if (err.message === 'tagObj must be a valid object') {
    console.error('Tag lookup failed; check the tag exists in tasks.json', { received: tagObj });
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling ensureTagMetadata(null), ensureTagMetadata(undefined), or passing a primitive such as a tag name string instead of the tag object, e.g. ensureTagMetadata(tag.name, opts) or passing a result of a lookup that returned null/undefined.

Common situations: A tag lookup (e.g. tasks data[tag]) returned undefined because the tag does not exist in tasks.json; refactored code accidentally passes the tag name instead of the tag object; JSON parsing produced null.

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


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/d8dfdf4f32e5920f. Report an issue: GitHub.