jackwener/OpenCLI · error · CliError

INVALID_INPUT

INVALID_INPUT

Error message

INVALID_INPUT

What it means

parseTarget first rejects inputs whose authority component is malformed (EMPTY_AUTHORITY_RE) — e.g. URLs like 'https://:password@' or 'https://@host' with an empty/degenerate userinfo. Zhihu write commands only accept normal HTTPS Zhihu URLs, so any input matching that pattern throws CliError with code INVALID_INPUT plus an example of the expected form.

Source

Thrown at clis/zhihu/target.js:17

import { CliError } from '@jackwener/opencli/errors';
const USER_RE = /^user:([A-Za-z0-9_-]+)$/;
const QUESTION_RE = /^question:(\d+)$/;
const ANSWER_RE = /^answer:(\d+):(\d+)$/;
const ARTICLE_RE = /^article:(\d+)$/;
const USER_PATH_RE = /^\/people\/([A-Za-z0-9_-]+)\/?$/;
const QUESTION_PATH_RE = /^\/question\/(\d+)\/?$/;
const ANSWER_PATH_RE = /^\/question\/(\d+)\/answer\/(\d+)\/?$/;
const ARTICLE_PATH_RE = /^\/p\/(\d+)\/?$/;
const EMPTY_AUTHORITY_RE = /^https:\/\/(?::)?@/i;
function isAllowedZhihuUrl(url) {
    return url.protocol === 'https:' && url.username === '' && url.password === '' && url.port === '';
}
export function parseTarget(input) {
    const value = String(input).trim();
    if (EMPTY_AUTHORITY_RE.test(value)) {
        throw new CliError('INVALID_INPUT', 'Zhihu write commands require a normal HTTPS Zhihu URL without malformed authority', 'Example: https://www.zhihu.com/question/123456');
    }
    if (value.startsWith('answer:') && !ANSWER_RE.test(value)) {
        throw new CliError('INVALID_INPUT', 'Invalid answer target, expected answer:<questionId>:<answerId>', 'Example: opencli zhihu like answer:123:456 --execute');
    }
    let match = value.match(USER_RE);
    if (match) {
        return { kind: 'user', slug: match[1], url: `https://www.zhihu.com/people/${match[1]}` };
    }
    match = value.match(QUESTION_RE);
    if (match) {
        return { kind: 'question', id: match[1], url: `https://www.zhihu.com/question/${match[1]}` };
    }
    match = value.match(ANSWER_RE);
    if (match) {
        return {
            kind: 'answer',
            questionId: match[1],
            id: match[2],

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Pass a plain URL without any userinfo: https://www.zhihu.com/question/123456
  2. Remove '@' and credentials from the argument; use the CLI's auth mechanism instead
  3. Quote the argument in the shell to prevent '@' or variable expansion issues

Example fix

// before
opencli zhihu like https://$USER@www.zhihu.com/answer/456 --execute
// after
opencli zhihu like https://www.zhihu.com/answer/456 --execute
Defensive patterns

Strategy: validation

Validate before calling

function isCleanZhihuUrl(s) {
  try {
    const u = new URL(String(s).trim());
    return u.protocol === 'https:' && u.hostname.endsWith('zhihu.com') &&
      u.username === '' && u.password === '';
  } catch { return false; }
}
if (!isCleanZhihuUrl(target)) throw new Error('strip credentials from the URL');

Type guard

function hasNoUserinfo(u) {
  return u instanceof URL && u.username === '' && u.password === '' && u.port === '';
}

Try / catch

try {
  const t = parseTarget(rawInput);
} catch (err) {
  if (err.code === 'INVALID_INPUT') {
    console.error('Bad target:', err.suggestion ?? err.message);
  } else throw err;
}

Prevention

When it happens

Trigger: Passing a URL with an empty username or password segment in the authority, e.g. 'https://@www.zhihu.com/question/123' or 'https://:x@www.zhihu.com/...', to any zhihu write command target.

Common situations: Pasting credentials into the URL from a shell history or script template, shell variable interpolation leaving an empty '@' segment (e.g. 'https://$USER@www.zhihu.com' with USER unset), copy-paste artifacts.

Related errors


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