eyaltoledano/claude-task-master · error

jsonPaths is required and must be an array

Error message

jsonPaths is required and must be an array

What it means

StreamParser.validate enforces its constructor contract: jsonPaths must be an array (it defines which JSON fields are streamed out of a larger stream). It throws when jsonPaths is undefined/null or not an array, catching misconfigured parsers before any stream processing starts.

Source

Thrown at src/utils/stream-parser.js:56

class StreamParserConfig {
	constructor(config = {}) {
		this.jsonPaths = config.jsonPaths;
		this.onProgress = config.onProgress;
		this.onError = config.onError;
		this.estimateTokens =
			config.estimateTokens || ((text) => Math.ceil(text.length / 4));
		this.expectedTotal = config.expectedTotal || 0;
		this.fallbackItemExtractor = config.fallbackItemExtractor;
		this.itemValidator =
			config.itemValidator || StreamParserConfig.defaultItemValidator;
		this.maxBufferSize = config.maxBufferSize || DEFAULT_MAX_BUFFER_SIZE;

		this.validate();
	}

	validate() {
		if (!this.jsonPaths || !Array.isArray(this.jsonPaths)) {
			throw new Error('jsonPaths is required and must be an array');
		}
		if (this.jsonPaths.length === 0) {
			throw new Error('jsonPaths array cannot be empty');
		}
		if (this.maxBufferSize <= 0) {
			throw new Error('maxBufferSize must be positive');
		}
		if (this.expectedTotal < 0) {
			throw new Error('expectedTotal cannot be negative');
		}
		if (this.estimateTokens && typeof this.estimateTokens !== 'function') {
			throw new Error('estimateTokens must be a function');
		}
		if (this.onProgress && typeof this.onProgress !== 'function') {
			throw new Error('onProgress must be a function');
		}
		if (this.onError && typeof this.onError !== 'function') {
			throw new Error('onError must be a function');

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Pass an array: new StreamParser({ jsonPaths: ['choices.0.delta.content'], ... })
  2. Wrap single paths in an array: Array.isArray(p) ? p : [p]
  3. Fix config loading so jsonPaths is parsed into an array (split(',') if it is a string).

Example fix

// before
new StreamParser({ jsonPaths: 'delta.text' });
// after
new StreamParser({ jsonPaths: ['delta.text'] });
Defensive patterns

Strategy: validation

Validate before calling

if (!Array.isArray(jsonPaths) || jsonPaths.length === 0) {
  throw new TypeError('jsonPaths must be a non-empty array of strings');
}
const parser = new StreamParser({ jsonPaths, ...opts });

Type guard

const isNonEmptyStringArray = (v) => Array.isArray(v) && v.length > 0 && v.every((s) => typeof s === 'string');

Try / catch

try {
  const parser = new StreamParser({ jsonPaths });
} catch (err) {
  if (err.message === 'jsonPaths is required and must be an array') {
    const parser = new StreamParser({ jsonPaths: Array.isArray(jsonPaths) ? jsonPaths : [String(jsonPaths)] });
  } else throw err;
}

Prevention

When it happens

Trigger: Constructing the StreamParser with no jsonPaths option, passing a string like 'data.items' instead of ['data.items'], or passing null/undefined from a config lookup.

Common situations: Config that stores comma-separated path strings instead of arrays; caller confusing a single path string with the required array; JSON schema/config migrations dropping the field.

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/414b48d2fe00499d. Report an issue: GitHub.