maboloshi/github-chinese · error · Error

HTTP ${res.status} ${url}

Error message

HTTP ${res.status} ${url}

What it means

fetchText() is the VS Code extension's helper that pulls the translation bundle (LOCALS_URL) and the main script (MAIN_URL) from the NJU mirror over globalThis.fetch at extension-activate time, bypassing page CSP. On any non-2xx response it throws HTTP <status> <url>. refreshSource() catches this and returns null, which leaves _source null and makes the status bar show '词库 ❌ 加载失败'; the error message appears in the extension host log.

Source

Thrown at vscode-extension/src/extension.ts:98

let _statusBar: vscode.StatusBarItem;
const _tabs = new Map<BrowserTabLike, TabEntry>();
let _source: string | null = null;

// ─── browser API 检测 ────────────────────────────────────────

function isBrowserApiAvailable(): boolean {
    const w = vscode.window as any;
    return typeof w.browserTabs !== 'undefined'
        && typeof w.onDidOpenBrowserTab === 'function'
        && typeof w.onDidCloseBrowserTab === 'function';
}

// ─── 注入源码构建 ─────────────────────────────────────────────

async function fetchText(url: string): Promise<string> {
    const res = await (globalThis as any).fetch(url);
    if (!res.ok) { throw new Error(`HTTP ${res.status} ${url}`); }
    return res.text();
}

/**
 * 构建注入源码:GM_* 兼容层 + 等 DOM 就绪后执行词库与主脚本(document-end 语义)。
 * 通过 CDP Page.addScriptToEvaluateOnNewDocument 直接注入(不 eval),
 * 规避 github.com CSP 对 eval 的限制(IBE 因用 new Function 被 CSP 拦截)。
 */
async function refreshSource(): Promise<string | null> {
    try {
        const [locals, main] = await Promise.all([fetchText(LOCALS_URL), fetchText(MAIN_URL)]);
        _source = `(function () {
'use strict';
/* ---- GM_* 兼容层(无 IBE 时补齐页面端 GM API)---- */
var gm = {
    addStyle: function (css) {
        var el = document.createElement('style');
        el.textContent = css;

View on GitHub (pinned to 1db777260a)

Solutions

  1. Check VS Code's proxy: set 'http.proxy' and 'http.proxyStrictSSL' appropriately, then reload the window so refreshSource re-fetches.
  2. Open https://mirror.nju.edu.cn/github-chinese/locals.js and .../main.user.js in a browser to confirm the mirror is up and the paths still resolve.
  3. If the NJU mirror is persistently unreachable, change LOCALS_URL/MAIN_URL in extension.ts to a reachable mirror (e.g. raw.githubusercontent gh-pages) and rebuild the extension.
  4. Run the extension's refresh command again once network is restored; injection is guarded on _source truthiness so it self-heals on a successful re-fetch.

Example fix

// before
async function fetchText(url: string): Promise<string> {
    const res = await (globalThis as any).fetch(url);
    if (!res.ok) { throw new Error(`HTTP ${res.status} ${url}`); }
    return res.text();
}
// after — retry transient 5xx/network errors with backoff
async function fetchText(url: string, tries = 3): Promise<string> {
    let last: Error | null = null;
    for (let i = 0; i < tries; i++) {
        try {
            const res = await (globalThis as any).fetch(url);
            if (res.ok) return res.text();
            last = new Error(`HTTP ${res.status} ${url}`);
            if (res.status < 500) throw last; // 4xx won't fix themselves
        } catch (e) { last = e as Error; }
        await new Promise(r => setTimeout(r, 500 * (i + 1)));
    }
    throw last ?? new Error(`fetch failed ${url}`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Before activation relies on the mirror, confirm reachability:
async function mirrorReachable(url: string): Promise<boolean> {
    try {
        const r = await (globalThis as any).fetch(url, { method: 'HEAD' });
        return r.ok;
    } catch {
        return false;
    }
}
// usage: if (!(await mirrorReachable(LOCALS_URL))) { showProxyHint(); }

Type guard

null

Try / catch

let src: string | null = null;
try {
    src = await refreshSource();
} catch (e) {
    console.error('[github-chinese] source refresh failed:', e);
    src = null;
}
if (!src) {
    vscode.window.showWarningMessage('GitHub 汉化资源拉取失败,请检查网络/代理/镜像');
    return;
}

Prevention

When it happens

Trigger: At activation (or when the refresh command runs) one of the two mirror URLs returns non-ok: a 404 if the mirror path changed, a 5xx while the mirror is down, or fetch throws (DNS/TLS/proxy/timeout) which surfaces as a rejected promise inside refreshSource's try. The thrown HTTP string is what the catch logs.

Common situations: Running VS Code behind a corporate proxy without http.proxy configured; the NJU mirror being down or rate-limiting; offline/cold start with no cached _source; a mirror path rename; a self-hosted environment that cannot reach mirror.nju.edu.cn.

Related errors


AI-assisted analysis of maboloshi/github-chinese@1db777260a (2026-08-13). Data as JSON: /api/errors/868e777d027dd5e9. Report an issue: GitHub.