immich-app/immich · error · Error

Hostname did not match any listed in methods[].allowedHosts

Error message

Hostname did not match any listed in methods[].allowedHosts in the plugin manifest

What it means

A plain Error thrown by the httpRequest host function when the requested URL's hostname does not match any regex pattern derived from the step's methods[].allowedHosts list. Each allowedHosts entry is converted to a regex ('.' -> '\.', '*' -> '.*') and tested against the URL hostname; if none match, the request is blocked as a security boundary.

Source

Thrown at server/src/services/workflow-execution.service.ts:107

      ]
    >(async (authDto, context, args) => {
      const hostname = new URL(args[0]).hostname;

      for (const pattern of context.allowedHosts) {
        const regex = new RegExp(pattern.replaceAll('.', String.raw`\.`).replaceAll('*', '.*'));
        if (regex.test(hostname)) {
          // eslint-disable-next-line unicorn/no-invalid-argument-count
          const res = await fetch(...args);

          return {
            ok: res.ok,
            status: res.status,
            body: await res.text(),
          };
        }
      }

      throw new Error('Hostname did not match any listed in methods[].allowedHosts in the plugin manifest');
    });

    const functions = {
      searchAlbums,
      createAlbum,
      addAssetsToAlbum,
      addAssetsToAlbums,
      httpRequest,
    };

    const stubs: typeof functions = {
      searchAlbums: dummy,
      createAlbum: dummy,
      addAssetsToAlbum: dummy,
      addAssetsToAlbums: dummy,
      httpRequest: dummy,
    };

View on GitHub (pinned to 199723261c)

Solutions

  1. Add the target hostname (or a matching wildcard like '*.example.com') to methods[].allowedHosts in the plugin manifest and re-import.
  2. Verify the regex translation: '*' becomes '.*' and '.' becomes a literal dot, so write allowedHosts accordingly.
  3. Prefer the narrowest matching pattern (e.g., 'api.example.com') over broad wildcards.
  4. After editing the manifest, force plugin re-import by changing its hash or restarting microservices.

Example fix

// before (manifest.json)
{ "methods": [{ "name": "fetchWeather", "allowedHosts": ["weather.io"] }] }
// plugin calls https://api.weather.io/... -> blocked

// after
{ "methods": [{ "name": "fetchWeather", "allowedHosts": ["*.weather.io"] }] }
Defensive patterns

Strategy: validation

Validate before calling

function isHostAllowed(url, allowedHosts) {
  const host = new URL(url).hostname;
  return allowedHosts.some((pattern) => {
    const re = new RegExp(pattern.replaceAll('.', '\\.').replaceAll('*', '.*'));
    return re.test(host);
  });
}
if (!isHostAllowed(targetUrl, manifest.methods[0].allowedHosts)) {
  return { ok: false, reason: 'Host not in allowedHosts' };
}

Type guard

const isAllowedHostsError = (e: unknown): boolean =>
  typeof e === 'object' && e !== null && typeof (e as any).message === 'string' &&
  (e as any).message.includes('allowedHosts');

Try / catch

// Surfaces inside httpRequest; validate host before the plugin calls it
if (!isHostAllowed(url, ctx.allowedHosts)) {
  return { ok: false, status: 0, body: 'blocked by allowedHosts' };
}

Prevention

When it happens

Trigger: A plugin calls httpRequest('https://api.example.com/...') but the method's allowedHosts in the manifest omits 'example.com' or lists a different domain. Wildcard patterns that do not cover the subdomain also fail.

Common situations: Plugin author lists allowedHosts but forgets a subdomain; wildcard '*.example.com' is expected but the pattern is written as 'example.com' (no wildcard); plugin switched to a different API host without updating the manifest; typo in the host entry.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/ccd9c4f71ee22acb. Report an issue: GitHub.