janhq/jan · error · Error

Invalid backend archive name

Error message

Invalid backend archive name: ${archiveName}

What it means

Defensive check after the archive-name regex has matched: the version and backend capture groups must both be non-empty. If the regex matched structurally but produced empty captures for version or backend (edge case in the regex), this error fires.

Solutions

  1. Rename the archive to follow the standard naming convention with explicit version and backend values.
  2. If this fires on a correctly-named file, inspect the regex for a regression and verify the capture groups.
Defensive patterns

Strategy: validation

Validate before calling

const BACKEND_ARCHIVE_RE = /^(.+?[-_])?llama(?:-main)?-(b\d+(?:-[a-f0-9]+)?)(?:-cudart-llama)?-bin-(.+?)\.(?:tar\.gz|zip)$/

function parseBackendArchive(name: string): { version: string; backend: string } | null {
  const m = BACKEND_ARCHIVE_RE.exec(name)
  if (!m || !m[2] || !m[3]) return null
  return { version: m[2], backend: m[3] }
}

// Before install:
const parsed = parseBackendArchive(archiveName)
if (!parsed) throw new Error('Cannot extract version and backend from archive name')

Type guard

function hasVersionAndBackend(match: RegExpMatchArray | null): match is RegExpMatchArray {
  return !!match && !!match[2] && !!match[3]
}

Prevention

When it happens

Trigger: An archive filename that technically satisfies the regex structure but has empty version or backend segments — this is rare given the regex requires non-empty patterns, but can occur with unexpected characters or a regex engine edge case.

Common situations: Extremely unusual filename constructions; regex was modified and introduced a bug allowing empty captures; an adversarial or corrupted filename.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/453f2d1941db3fef. Report an issue: GitHub.

Appendix: source

Thrown at extensions/llamacpp-extension/src/index.ts:2873

      !(await fs.existsSync(path)) ||
      (!path.endsWith('tar.gz') && !path.endsWith('zip'))
    ) {
      logger.error(`Invalid path or file ${path}`)
      throw new Error(`Invalid path or file ${path}`)
    }

    const match = re.exec(archiveName)

    if (!match) {
      throw new Error(
        `Failed to parse archive name: ${archiveName}. Expected format: [Optional prefix-]llama-<version>-bin-<backend>.(tar.gz|zip)`
      )
    }

    const [, prefix, version, backend] = match

    if (!version || !backend) {
      throw new Error(`Invalid backend archive name: ${archiveName}`)
    }

    // Include prefix in the backend identifier if present
    const backendIdentifier = prefix ? `${prefix}${backend}` : backend

    logger.info(
      `Detected prefix: ${prefix || 'none'}, version: ${version}, backend: ${backendIdentifier}`
    )

    const backendDir = await getBackendDir(backendIdentifier, version)

    try {
      await invoke('decompress', { path: path, outputDir: backendDir })
    } catch (e) {
      logger.error(`Failed to install: ${String(e)}`)
      throw new Error(`Failed to decompress archive: ${String(e)}`)
    }

View on GitHub (pinned to fad3f12a14)