jackwener/OpenCLI · error · CommandExecutionError

${label} returned a malformed string

Error message

${label} returned a malformed string

What it means

readOptionalString validates that an optional string field is null/undefined or a string; anything else throws this CommandExecutionError. It is used by the redirectUrl accessor of the bilibili video command.

Source

Thrown at clis/bilibili/video.js:29

function unwrapBrowserResult(value) {
  if (value && typeof value === 'object' && typeof value.session === 'string' && Object.hasOwn(value, 'data')) {
    return value.data;
  }
  return value;
}

function readOptionalFlag(value, label) {
  if (value == null) return false;
  if (typeof value === 'boolean') return value;
  if (typeof value === 'number') return value !== 0;
  throw new CommandExecutionError(`${label} returned a malformed flag`);
}

function readOptionalString(value, label) {
  if (value == null) return '';
  if (typeof value === 'string') return value;
  throw new CommandExecutionError(`${label} returned a malformed string`);
}

cli({
  site: 'bilibili',
  name: 'video',
    access: 'read',
  description: 'Get Bilibili video metadata (title, author, duration, stats, etc.)',
  strategy: Strategy.COOKIE,
  args: [
    { name: 'bvid', required: true, positional: true, help: 'BV ID, video URL, or b23.tv short link' },
    { name: 'page', required: false, help: '分P 选集序号(从 1 开始)。多 P 视频指定某一集,title/cid 返回该集;缺省取整集默认(P1)' },
  ],
  columns: ['field', 'value'],
  func: async (page, kwargs) => {
    if (!page) {
      throw new CommandExecutionError('Browser session required for bilibili video');
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the raw value for the failing video to see the unexpected type
  2. Coerce safe cases (e.g. String(value)) if the field is reliably scalar
  3. Catch the error and return '' for redirect_url so the rest of the output still renders
  4. Update the field handling in clis/bilibili/video.js if the API schema changed

Example fix

// before
if (typeof value === 'string') return value;
throw new CommandExecutionError(`${label} returned a malformed string`);
// after
if (typeof value === 'string') return value;
if (typeof value === 'number') return String(value);
throw new CommandExecutionError(`${label} returned a malformed string`);
Defensive patterns

Strategy: type-guard

Validate before calling

null

Type guard

function isOptionalString(v) {
  return v == null || typeof v === 'string';
}

Try / catch

try { const info = await getVideoInfo(bvid); }
catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('malformed string')) { console.warn('redirect_url had unexpected type'); }
  else throw e;
}

Prevention

When it happens

Trigger: The video API's redirect_url (or similar string field) arrives as a number, object, or array instead of a string — schema drift or an unusual video entry shape.

Common situations: Bilibili changing a field's type; certain videos (deleted, region-locked) returning structured error objects where a string is expected; middleware JSON transformations.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/d26d7df255bc64e8. Report an issue: GitHub.