astrid-runtime/astrid · error

seal can only resolve GitHub-backed capsule sources (@org/re

Error message

seal can only resolve GitHub-backed capsule sources (@org/repo); got {source:?}

What it means

`seal` (capsule installation) resolves capsule sources exclusively from GitHub repositories in `@org/repo` form. `resolve_capsule_to_file` throws this error when `parse_github_source` cannot extract an org/repo pair from the given source string, e.g. when a local path, bare name, URL, or other registry scheme is passed.

Source

Thrown at crates/astrid-cli/src/commands/capsule/install.rs:421

/// release assets, so a missing asset is a hard error the maintainer
/// must resolve.
/// `name_hint` is the distro capsule `name`, used to pick the right
/// archive when one source ships several (a monorepo builds/releases one
/// `.capsule` per capsule crate) — the same `capsule_assets`/`pick_capsule`
/// selection [`install_from_github`] uses. A single-asset release installs
/// that one regardless of the hint.
/// The returned ref is the single source of truth the seal records in
/// the lock's `resolved_ref`: it is whatever GitHub reported as the
/// release `tag_name`, never an optimistic guess from the manifest.
pub(crate) async fn resolve_capsule_to_file(
    source: &str,
    version: Option<&str>,
    tag: Option<&str>,
    name_hint: Option<&str>,
    dest_path: &Path,
) -> anyhow::Result<String> {
    let (org, repo) = parse_github_source(source).ok_or_else(|| {
        anyhow::anyhow!(
            "seal can only resolve GitHub-backed capsule sources (@org/repo); got {source:?}"
        )
    })?;

    // Authenticated when a token is present (see `github_api_client`).
    let client = github_api_client()?;

    let resolved_ref = resolve_github_ref(&client, &org, &repo, version, tag).await?;

    // Fetch the resolved release's assets and pick the right `<name>.capsule`
    // (the same selection the install path uses), so a release shipping
    // several capsules downloads the one the seal asked for rather than the
    // first. A missing `.capsule` asset is a hard error — seal requires
    // pre-built release artifacts.
    let api_url = release_tag_url(&org, &repo, &resolved_ref)?;
    let response = client
        .get(&api_url)
        .send()

View on GitHub (pinned to affd8760f4)

Solutions

  1. Use the `@org/repo` form for the source, e.g. `@acme/my-capsule`
  2. If installing from a local file, use the local-path install path instead of `seal`'s GitHub resolver
  3. Check for typos: exactly one `@` at the start and exactly one `/` separating org and repo

Example fix

// before
seal --source my-capsule
// after
seal --source @acme/my-capsule
Defensive patterns

Strategy: validation

Validate before calling

fn is_github_source(source: &str) -> bool {
    let rest = source.strip_prefix('@')?;
    let (org, repo) = rest.split_once('/')?;
    Some(()).filter(|_| !org.is_empty() && !repo.is_empty() && !repo.contains('/')).is_some()
}
if !is_github_source(source) { /* fix or route to local installer */ }

Type guard

fn as_github_source(source: &str) -> Option<(&str, &str)> {
    let rest = source.strip_prefix('@')?;
    let (org, repo) = rest.split_once('/')?;
    (!org.is_empty() && !repo.is_empty() && !repo.contains('/')).then(|| (org, repo))
}

Prevention

When it happens

Trigger: Calling `resolve_capsule_to_file` (via `stage_capsule`) with a source that is not `@org/repo`: a local file path, an https:// URL, a bare capsule name without the `@` prefix, or a malformed ref like `@org` or `org/repo` (missing `@`).

Common situations: Typing the capsule name without the `@org/` prefix; pointing seal at a locally-built capsule archive instead of a GitHub release; pasting a full GitHub URL instead of the shorthand; typos like `@org/repo/extra`.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/b5a864672c6cae80. Report an issue: GitHub.