jackwener/OpenCLI · error · ArgumentError

Novel download format must be txt or md

Error message

Novel download format must be txt or md

What it means

normalizeNovelFileFormat rejects a --format argument that is defined but not a string, throwing this ArgumentError before any download starts. Only string values can be normalized to txt or md.

Source

Thrown at clis/pixiv/novel-download-utils.js:49

  const createdDate = dateOnly(body.createDate);
  const wordCount = optionalDownloadCount(body.wordCount, 'word count');
  const bookmarkCount = optionalDownloadCount(body.bookmarkCount, 'bookmark count');
  return {
    ...body,
    id: novelId,
    title,
    userName: author,
    userId,
    content: body.content,
    createdDate,
    wordCount,
    bookmarkCount,
  };
}

export function normalizeNovelFileFormat(value) {
  if (value !== undefined && typeof value !== 'string') {
    throw new ArgumentError('Novel download format must be txt or md');
  }
  const format = (value ?? 'txt').toLowerCase();
  if (format !== 'txt' && format !== 'md') {
    throw new ArgumentError(`Unsupported novel download format: ${format}. Supported formats: txt, md.`);
  }
  return format;
}

export function normalizePixivOutputRoot(value, fallback) {
  if (value !== undefined && typeof value !== 'string') {
    throw new ArgumentError('output must be a directory path');
  }
  const raw = value ?? fallback;
  if (!raw || raw.includes('\0')) {
    throw new ArgumentError('output must be a non-empty directory path');
  }
  const resolved = path.resolve(raw);
  let ancestor = resolved;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Quote the format value in config so parsers keep it a string: format: "txt"
  2. Pass only 'txt' or 'md' as the format
  3. Fix the config schema/parser that is coercing the value to a non-string

Example fix

// before (config.yaml)
format: true
// after
format: "md"
Defensive patterns

Strategy: validation

Validate before calling

const fmt = options.format;
if (fmt !== undefined && typeof fmt !== 'string') {
  throw new Error(`format must be a string ('txt' or 'md'), got ${typeof fmt}`);
}

Type guard

const isFormatValue = (v) => v === undefined || typeof v === 'string';

Try / catch

try {
  await novelDownload({ format });
} catch (e) {
  if (e.message === 'Novel download format must be txt or md') {
    console.error('format must be a string; check your config parser types');
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a non-string to the format option programmatically (number, boolean, object) via the API or a config loader that yields typed values.

Common situations: Config file parsed with a YAML/JSON parser producing a boolean/number for format (e.g. format: true or format: 1); calling the exported function directly with a wrong type.

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 jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/fef5ec6502ac09d2. Report an issue: GitHub.