iOfficeAI/AionUi · error · Error

update.errors.invalidUrl

update.errors.invalidUrl

Error message

update.errors.invalidUrl

What it means

Thrown by assertAllowedUrl in the update bridge when the URL string passed to the updater cannot be parsed by the URL constructor. It is the first validation step before protocol and host checks, so any syntactically invalid URL (empty string, missing scheme, malformed characters) triggers it.

Source

Thrown at packages/desktop/src/process/bridge/updateBridge.ts:275

    prerelease: false,
    draft: false,
    assets,
    recommendedAsset: pickRecommendedAsset(assets),
  };
};

const resolveRepo = (requestRepo?: string): string => {
  const envRepo = process.env.AIONUI_GITHUB_REPO?.trim();
  const repo = (requestRepo || envRepo || DEFAULT_REPO).trim();
  return repo || DEFAULT_REPO;
};

const assertAllowedUrl = async (rawUrl: string) => {
  let parsed: URL;
  try {
    parsed = new URL(rawUrl);
  } catch {
    throw new Error((await getI18n()).t('update.errors.invalidUrl'));
  }

  if (parsed.protocol !== 'https:') {
    throw new Error((await getI18n()).t('update.errors.httpsOnly'));
  }
  if (!ALLOWED_DOWNLOAD_HOSTS.has(parsed.hostname)) {
    throw new Error((await getI18n()).t('update.errors.hostNotAllowed', { host: parsed.hostname }));
  }
};

const fetchWithAllowlistedRedirects = async (rawUrl: string, signal: AbortSignal): Promise<Response> => {
  let current = rawUrl;

  for (let i = 0; i <= MAX_REDIRECTS; i++) {
    await assertAllowedUrl(current);

    const res = await fetch(current, {
      signal,

View on GitHub (pinned to 711aa0550e)

Solutions

  1. Check the URL string being passed — it must be a fully qualified absolute URL
  2. Add the https:// scheme if it is missing
  3. Trim whitespace/newlines from config-sourced URLs before passing them
  4. Reset or fix the stored update configuration if it was corrupted
  5. Log the raw value before the call to identify where the bad string originates

Example fix

// before
await assertAllowedUrl(feedUrl); // feedUrl = 'example.com/app.json'

// after
const normalized = feedUrl.trim();
await assertAllowedUrl(
  /^https?:\/\//.test(normalized) ? normalized : `https://${normalized}`,
);
Defensive patterns

Strategy: validation

Validate before calling

const isValidAbsoluteUrl = (s: string): boolean => {
  try {
    const u = new URL(s.trim());
    return u.protocol === 'http:' || u.protocol === 'https:';
  } catch {
    return false;
  }
};
if (!isValidAbsoluteUrl(feedUrl)) throw new Error('configure a valid https update URL');
await initUpdateBridge(feedUrl);

Type guard

const isParsableUrl = (v: unknown): v is string =>
  typeof v === 'string' &&
  (() => { try { new URL(v.trim()); return true; } catch { return false; } })();

Try / catch

try {
  await assertAllowedUrl(url);
} catch (err) {
  if (err instanceof Error && err.message.includes('invalidUrl')) {
    // sanitize: trim, prepend https:// if scheme missing, then retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling any update API that funnels through assertAllowedUrl (fetchWithAllowlistedRedirects, runWithFallback, initUpdateBridge) with a non-URL string: '', 'github.com/owner/repo' (no scheme), 'https://' alone, or a URL with invalid control characters.

Common situations: A misconfigured update feed URL in settings/config that omits https://; a template string that evaluated to undefined and became 'undefined'; trailing whitespace or newline in a config-provided URL; corrupted persisted app config after an upgrade.

Related errors


AI-assisted analysis of iOfficeAI/AionUi@711aa0550e (2026-08-28). Data as JSON: /api/errors/b424c682af772ea9. Report an issue: GitHub.