denoland/deno · error

Invalid registry configuration. Url

Error message

Invalid registry configuration. Url "{}" (for variable "{}" in registry with schema "{}") uses variable "{}", which is not allowed because that would be a self reference.

What it means

Thrown by the Deno language server while validating a third-party autocomplete registry configuration (the JSON the LSP fetches for a completion host configured under deno.suggest.imports.hosts). In a "version": 1 configuration, each variable's "url" template may only substitute variables the schema defines to its left; a URL that substitutes the variable's own key is rejected as a self reference because v1 resolution has no value for the key being looked up. The check at cli/lsp/registries.rs:348 only applies when config.version == 1, so version 2 configs are allowed to self-reference.

Solutions

  1. Set "version": 2 in the registry configuration JSON — version 2 explicitly permits a variable URL to reference its own key.
  2. Remove the self reference: make the variable's "url" a concrete endpoint with no ${...} placeholder for its own key, e.g. "https://example.com/modules" for key "module".
  3. If the endpoint genuinely needs the key's value, restructure the schema so another variable supplies that information earlier in the path.

Example fix

// before (registries.json)
{
  "version": 1,
  "registries": [
    {
      "schema": ":module",
      "variables": [
        { "key": "module", "url": "https://example.com/modules/${module}" }
      ]
    }
  ]
}

// after
{
  "version": 2,
  "registries": [
    {
      "schema": ":module",
      "variables": [
        { "key": "module", "url": "https://example.com/modules/${module}" }
      ]
    }
  ]
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate a registry configuration before pointing the Deno LSP at it
// (mirrors validate_config in cli/lsp/registries.rs for self references).
export function assertNoSelfReferences(config) {
  if (config.version === 1) {
    for (const registry of config.registries ?? []) {
      for (const v of registry.variables ?? []) {
        if (v.url.includes(`\$\{${v.key}\}`)) {
          throw new Error(`variable '${v.key}' self-references in '${v.url}' — use version 2 or remove the reference`);
        }
      }
    }
  }
}

Type guard

// Narrow an unknown payload to a v2 registry config (self references allowed).
export function isV2RegistryConfig(c) {
  return typeof c === 'object' && c !== null && c.version === 2 &&
    Array.isArray(c.registries) &&
    c.registries.every((r) =>
      typeof r?.schema === 'string' && Array.isArray(r?.variables) &&
      r.variables.every((v) => typeof v?.key === 'string' && typeof v?.url === 'string')
    );
}

Prevention

When it happens

Trigger: A registry configuration declares "version": 1 and contains a variable whose "url" embeds a placeholder equal to the variable's own "key", e.g. schema ":module" with {"key": "module", "url": "https://example.com/modules/${module}"}. Validation runs when the LSP fetches and parses the registry config (startup or first completion request) and fails the whole config load.

Common situations: Authoring a custom completion registry for the Deno VS Code extension; copying a version 2 registry file (which permits self references) into a config that still declares version 1; migrating the old deno.land/x registry format by hand and forgetting to bump the version field.

Related errors


AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20). Data as JSON: /api/errors/7880deb70a72fe7f. Report an issue: GitHub.

Appendix: source

Thrown at cli/lsp/registries.rs:358

        .any(|x| x == *key_name)
      {
        return Err(anyhow!(
          "Invalid registry configuration. Registry with schema \"{}\" is missing variable declaration for key \"{}\".",
          registry.schema,
          key_name
        ));
      }
    }

    for variable in &registry.variables {
      let key_index = key_names.iter().position(|key| *key == variable.key);
      let key_index = key_index.ok_or_else(||anyhow!("Invalid registry configuration. Registry with schema \"{}\" is missing a path parameter in schema for variable \"{}\".", registry.schema, variable.key))?;

      let replacement_variables = parse_replacement_variables(&variable.url);
      let limited_keys = key_names.get(0..key_index).unwrap();
      for v in replacement_variables {
        if variable.key == v && config.version == 1 {
          return Err(anyhow!(
            "Invalid registry configuration. Url \"{}\" (for variable \"{}\" in registry with schema \"{}\") uses variable \"{}\", which is not allowed because that would be a self reference.",
            variable.url,
            variable.key,
            registry.schema,
            v
          ));
        }

        let key_index = limited_keys.iter().position(|key| key == &v);

        if key_index.is_none() && variable.key != v {
          return Err(anyhow!(
            "Invalid registry configuration. Url \"{}\" (for variable \"{}\" in registry with schema \"{}\") uses variable \"{}\", which is not allowed because the schema defines \"{}\" to the right of \"{}\".",
            variable.url,
            variable.key,
            registry.schema,
            v,
            v,

View on GitHub (pinned to f7822238ca)