{"record":{"id":"7ef6c03e01ec76cd","repo":"jdx/mise","slug":"unexpected-character","errorCode":null,"errorMessage":"unexpected character: {}","messagePattern":"unexpected character: (.+?)","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"crates/aqua-registry/src/template.rs","lineNumber":182,"sourceCode":"                tokens.push(Token::Dot);\n                code = &code[1..];\n            }\n        } else {\n            // Check if it's an identifier (alphanumeric starting with letter)\n            let end = code\n                .chars()\n                .enumerate()\n                .find(|(_, c)| !c.is_alphanumeric() && *c != '_' && *c != '-')\n                .map(|(i, _)| i)\n                .unwrap_or(code.len());\n\n            if end > 0 {\n                let token_str = &code[..end];\n                // Determine if this is a function or identifier based on context\n                tokens.push(Token::Func(token_str));\n                code = &code[end..];\n            } else {\n                bail!(\"unexpected character: {}\", code.chars().next().unwrap());\n            }\n        }\n    }\n    Ok(tokens)\n}\n\nfn dotted_identifier_end(code: &str) -> Option<usize> {\n    let rest = code.strip_prefix('.')?;\n    let first = rest.chars().next()?;\n    if !first.is_alphabetic() {\n        return None;\n    }\n    Some(1 + identifier_len(rest))\n}\n\nfn identifier_len(code: &str) -> usize {\n    code.char_indices()\n        .find(|(_, c)| !c.is_alphanumeric() && *c != '_')","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/crates/aqua-registry/src/template.rs#L164-L200","documentation":"After parsing all artifacts, mise requires at least one installable artifact category to be non-empty (apps, binaries, command_wrappers, pkgs, installers, generic, fonts, completions, generated_completions). If the cask's artifacts list is empty or contains only ignored non-install kinds (caveats, depends_on, uninstall, zap, ...), there is nothing mise can install and it bails.","triggerScenarios":"A cask whose JSON artifacts array is empty; a cask defined purely by metadata (conflicts_with/depends_on/uninstall) with no real payload; API responses where artifacts live under a key mise reads differently.","commonSituations":"Metadata-only or 'skip' style casks; casks whose entire payload is an unsupported stanza that was silently ignored rather than bailed; corrupt API cache.","solutions":["Inspect the cask's JSON (brew info --cask=v2 --json <token>) to see what artifacts it actually declares","Update mise in case the artifact shape is newly supported","Clear the cached Homebrew API data and retry so fresh metadata is fetched","Install the cask with upstream brew and report the token to mise"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let has_payload = cask.artifacts.iter().any(|a| {\n    let k = artifact_type(a);\n    matches!(k.as_str(), \"app\" | \"binary\" | \"pkg\" | \"installer\" | \"generic_artifact\" | \"font\" | \"completion\")\n});\nif !has_payload { /* skip this cask before install */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check cask JSON for a real payload stanza before adding it to mise.toml","Keep Homebrew API caches fresh so artifact lists are not stale-empty"],"tags":["rust","mise","brew-cask","artifact-validation"],"backgroundTag":"no-installable-artifact","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}