{"record":{"id":"8358199778a70500","repo":"astrid-runtime/astrid","slug":"branding-primary-color-e","errorCode":null,"errorMessage":"branding.primary-color: {e}","messagePattern":"branding\\.primary-color: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/distro/validate.rs","lineNumber":249,"sourceCode":"                \"invites.max-principals must be \\\"unlimited\\\" or a non-negative integer (got {cap:?})\",\n            );\n        }\n    }\n\n    // Branding — only structural rails. The dashboard interprets the\n    // values; the parser just refuses obvious garbage.\n    if let Some(branding) = &manifest.branding {\n        if let Some(icon) = &branding.icon\n            && icon.len() > 64 * 1024\n        {\n            anyhow::bail!(\n                \"branding.icon is {} bytes — distros must not embed assets larger than 64 KiB\",\n                icon.len()\n            );\n        }\n        if let Some(color) = &branding.primary_color {\n            validate_hex_color(color)\n                .map_err(|e| anyhow::anyhow!(\"branding.primary-color: {e}\"))?;\n        }\n        if let Some(color) = &branding.accent_color {\n            validate_hex_color(color).map_err(|e| anyhow::anyhow!(\"branding.accent-color: {e}\"))?;\n        }\n    }\n\n    Ok(())\n}\n\n/// Enforce a manifest's `[distro].astrid-version` floor against the running CLI.\n///\n/// Called on the init / `distro apply` path *after* the manifest is fetched and\n/// parsed but *before* any prompting or install, so a distro whose `Distro.toml`\n/// (fetched from the repo `main` tip) bumps its CLI floor fails fast with an\n/// actionable message instead of breaking onboarding mid-flight on an older CLI.\n///\n/// A manifest with no `astrid-version` floor imposes no requirement.\npub(crate) fn enforce_astrid_version(manifest: &DistroManifest) -> anyhow::Result<()> {","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/distro/validate.rs#L231-L267","documentation":"validate_manifest checks [branding].primary-color with validate_hex_color and prefixes any parser error with 'branding.primary-color:'. It fires when the configured color is not a valid hex color (e.g. wrong length, missing '#', non-hex characters).","triggerScenarios":"A Distro.toml with branding.primary-color set to values like 'red', 'FF0000' (no #), '#F00' if shorthand is unsupported, '#GGGGGG', or an empty string.","commonSituations":"Authors pasting CSS named colors or rgb() values instead of hex; losing the '#' when hand-editing TOML; copy-pasting from design tools that emit 8-digit ARGB or uppercase prefixes.","solutions":["Set primary-color to a valid hex color in '#rrggbb' form (e.g. '#336699').","Match the exact format validate_hex_color accepts (check whether 3-digit shorthand is allowed).","Remove the branding.primary-color key to fall back to the default theme."],"exampleFix":"# before (Distro.toml)\n[branding]\nprimary-color = \"blue\"\n# after\n[branding]\nprimary-color = \"#0000ff\"","handlingStrategy":"validation","validationCode":"fn is_hex_color(s: &str) -> bool {\n    let t = s.strip_prefix('#').unwrap_or(s);\n    t.len() == 6 && t.chars().all(|c| c.is_ascii_hexdigit())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only use #rrggbb literals in branding fields.","Convert from design-tool outputs to hex before pasting.","Run `astrid distro validate` locally before pushing the manifest."],"tags":["config","validation","color","manifest"],"backgroundTag":"invalid-config-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}