astrid-runtime/astrid · error

branding.icon is bytes — distros must not embed assets…

Error message

branding.icon is {} bytes — distros must not embed assets larger than 64 KiB

What it means

Fired by validate_manifest in distro validation when the decoded branding.icon asset exceeds 64 KiB. Distro manifests must not embed large binary assets; icons above this size are rejected to keep manifests lightweight.

Solutions

  1. Replace the icon with a smaller optimized asset under 64 KiB (resize/compress the image).
  2. Reference the icon externally instead of embedding it in the manifest.
  3. If embedding is required, strip metadata and reduce resolution/color depth to fit the cap.

Example fix

// before
branding.icon = "<87000-byte base64 PNG>"

// after
branding.icon = "<optimized 32x32 PNG, ~4KB base64>"
Defensive patterns

Strategy: validation

Validate before calling

fn icon_size_ok(icon: &[u8]) -> bool {
    icon.len() <= 64 * 1024
}
// call before writing manifest:
assert!(icon_size_ok(&icon_bytes), "icon must be <= 64 KiB");

Type guard

fn embeddable_icon(icon: &[u8]) -> Option<&[u8]> {
    (icon.len() <= 64 * 1024).then_some(icon)
}

Try / catch

if icon.len() > 64 * 1024 {
    eprintln!("icon is {} bytes; compress below 64 KiB", icon.len());
    std::process::exit(1);
}

Prevention

When it happens

Trigger: Setting branding.icon to a data blob (e.g. base64 or raw bytes) longer than 64 * 1024 bytes. Detected during any distro manifest validation.

Common situations: Exporting a high-resolution logo without downscaling; pasting a full-size PNG/SVG asset into the manifest instead of an optimized icon; accidental duplication of the asset payload.

Understand the failure class

Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.

Related errors


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

Appendix: source

Thrown at crates/astrid-cli/src/commands/distro/validate.rs:242

            parse_invite_duration(exp).map_err(|e| anyhow::anyhow!(e))?;
        }
        if let Some(cap) = &invites.max_principals
            && cap != "unlimited"
            && cap.parse::<u32>().is_err()
        {
            anyhow::bail!(
                "invites.max-principals must be \"unlimited\" or a non-negative integer (got {cap:?})",
            );
        }
    }

    // Branding — only structural rails. The dashboard interprets the
    // values; the parser just refuses obvious garbage.
    if let Some(branding) = &manifest.branding {
        if let Some(icon) = &branding.icon
            && icon.len() > 64 * 1024
        {
            anyhow::bail!(
                "branding.icon is {} bytes — distros must not embed assets larger than 64 KiB",
                icon.len()
            );
        }
        if let Some(color) = &branding.primary_color {
            validate_hex_color(color)
                .map_err(|e| anyhow::anyhow!("branding.primary-color: {e}"))?;
        }
        if let Some(color) = &branding.accent_color {
            validate_hex_color(color).map_err(|e| anyhow::anyhow!("branding.accent-color: {e}"))?;
        }
    }

    Ok(())
}

/// Enforce a manifest's `[distro].astrid-version` floor against the running CLI.
///

View on GitHub (pinned to affd8760f4)