astrid-runtime/astrid · error
signed channel names
Error message
signed channel names '{}', expected '{}' What it means
validate_pointer checks a signed channel pointer (TOML metadata describing the latest release on an update channel). This error fires when the pointer's `channel` field does not match the channel the caller expected to fetch, e.g. fetching the stable channel but the file says `dev`. It guards against channel-confusion or a tampered/misrouted metadata file.
Solutions
- Fetch the channel metadata from the URL corresponding to the channel you intend (stable vs dev vs nightly) and retry
- Inspect the pointer's `channel` field in the signed TOML and confirm which channel it actually describes
- If you mirror feeds locally, regenerate/sync the mirror so each channel directory holds its own pointer
- Verify the signing/publication workflow writes the pointer under the matching channel name
Example fix
// before: fetching stable metadata from the nightly feed
let bytes = fetch("https://updates.example.com/nightly/channel.toml").await?;
let ptr = parse_channel(&bytes, UpdateChannel::Stable, now)?; // channel names 'nightly', expected 'stable'
// after
let bytes = fetch("https://updates.example.com/stable/channel.toml").await?;
let ptr = parse_channel(&bytes, UpdateChannel::Stable, now)?; Defensive patterns
Strategy: validation
Validate before calling
fn channel_matches(pointer_toml: &str, expected: UpdateChannel) -> bool {
pointer_toml.contains(&format!("channel = \"{}\"", expected.as_str()))
}
// call before parse_channel: channel_matches(&bytes_text, UpdateChannel::Stable) Type guard
fn is_expected_channel(p: &ChannelPointer, expected: &UpdateChannel) -> bool {
p.channel == expected.as_str()
} Try / catch
match parse_channel(&bytes, expected, now) {
Ok(ptr) => ptr,
Err(e) if e.to_string().contains("signed channel names") => {
eprintln!("fetched wrong channel feed: {e}");
// re-fetch from the correct channel URL
retry_with_correct_url(expected).await?
}
Err(e) => return Err(e),
} Prevention
- Derive the metadata URL from the UpdateChannel enum instead of hardcoding per-channel paths
- Never copy a channel.toml between channel directories
- Log the pointer's channel field when a fetch succeeds so mismatches surface immediately
- Use enforce_continuity in tests to catch cross-channel swaps in mirrors
When it happens
Trigger: parse_channel(bytes, expected_channel, now) or enforce_continuity is called with signed channel bytes whose `channel` field differs from `expected_channel.as_str()` (mismatch like "nightly" vs "stable"), typically because the wrong channel URL was fetched or the pointer was swapped.
Common situations: Misconfigured update-feed base URL pointing at another channel's directory; a CDN/redirect serving cached metadata from a different channel; hand-edited channel metadata; signing pipeline publishing to the wrong channel path.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- branding.accent-color
- branding.primary-color
- Cargo include table must contain a string path in
- distro.astrid-version
- {e}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/bdd9efcb87c7240d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/update_channel.rs:469
let pointer: ChannelPointer =
toml::from_str(text).context("signed channel metadata is invalid TOML")?;
validate_pointer(&pointer, expected_channel, Some(now))?;
Ok(pointer)
}
fn validate_pointer(
pointer: &ChannelPointer,
expected_channel: UpdateChannel,
now: Option<DateTime<Utc>>,
) -> anyhow::Result<()> {
ensure!(
pointer.schema_version == 1
&& pointer.kind == "astrid-channel"
&& pointer.product == PRODUCT
&& pointer.repository == REPOSITORY,
"signed channel identity is invalid"
);
ensure!(
pointer.channel == expected_channel.as_str(),
"signed channel names '{}', expected '{}'",
pointer.channel,
expected_channel.as_str()
);
ensure!(
pointer.generation > 0,
"signed channel generation must be positive"
);
let published = canonical_time(&pointer.published_at, "published-at")?;
let expires = canonical_time(&pointer.expires_at, "expires-at")?;
ensure!(expires > published, "signed channel lifetime is invalid");
if let Some(now) = now {
ensure!(now <= expires, "signed channel metadata has expired");
let latest_reasonable_publication = now
.checked_add_signed(chrono::Duration::seconds(MAX_FUTURE_SKEW_SECS))
.context("channel publication skew overflowed the clock")?;
ensure!(View on GitHub (pinned to affd8760f4)