{"record":{"id":"c1d1a94f434c7853","repo":"sigoden/aichat","slug":"no-document-loader-for","errorCode":null,"errorMessage":"No document loader for '{}'","messagePattern":"No document loader for '(.+?)'","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/utils/loader.rs","lineNumber":103,"sourceCode":"\npub fn is_loader_protocol(loaders: &HashMap<String, String>, path: &str) -> bool {\n    match path.split_once(':') {\n        Some((protocol, _)) => loaders.contains_key(protocol),\n        None => false,\n    }\n}\n\npub fn load_protocol_path(\n    loaders: &HashMap<String, String>,\n    path: &str,\n) -> Result<Vec<LoadedDocument>> {\n    let (protocol, loader_command, new_path) = path\n        .split_once(':')\n        .and_then(|(protocol, path)| {\n            let loader_command = loaders.get(protocol)?;\n            Some((protocol, loader_command, path))\n        })\n        .ok_or_else(|| anyhow!(\"No document loader for '{}'\", path))?;\n    let contents = run_loader_command(new_path, protocol, loader_command)?;\n    let output = if let Ok(list) = serde_json::from_str::<Vec<LoadedDocument>>(&contents) {\n        list.into_iter()\n            .map(|mut v| {\n                if v.path.starts_with(path) {\n                } else if v.path.starts_with(new_path) {\n                    v.path = format!(\"{}:{}\", protocol, v.path);\n                } else {\n                    v.path = format!(\"{}/{}\", path, v.path);\n                }\n                v\n            })\n            .collect()\n    } else {\n        vec![LoadedDocument::new(\n            path.into(),\n            contents,\n            Default::default(),","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/sigoden/aichat/blob/82976d349ad97ac9aae0655ad631dace5e2a6385/src/utils/loader.rs#L85-L121","documentation":"`load_protocol_path` parses a path of the form `protocol:rest`, looks the protocol up in the configured `loaders` map, and returns `anyhow!(\"No document loader for '{}'\", path)` when the protocol is missing or the path has no `protocol:` prefix at all (`split_once(':')` yields None). It means the given URI scheme has no loader registered, so the document cannot be fetched.","triggerScenarios":"Calling `load_protocol_path` (directly or via `load_documents`/`sync_documents`) with a path whose prefix is absent from the `loaders` map, e.g. `s3:docs/report.md` when only `http` is configured, or a plain `README.md` with no colon at all.","commonSituations":"Typo'd protocol in a document list; loader removed or renamed in config while old references remain; forgetting to register a loader for a scheme used in a docs index.","solutions":["Register a loader for the protocol: add an entry to the `loaders` map keyed by the scheme in the path.","Fix the path to use a protocol that has a configured loader.","Check for typos between the path prefix and the loader key (e.g. `https:` vs `http:`).","Validate all document paths against the loader keys before starting a sync run."],"exampleFix":"// before\nlet mut loaders = HashMap::new();\nloaders.insert(\"http\", \"curl -L $1\");\nload_protocol_path(\"s3:manual.md\", &loaders)?; // No document loader for 's3:manual.md'\n// after\nloaders.insert(\"s3\", \"aws s3 cp $1 -\");\nload_protocol_path(\"s3:manual.md\", &loaders)?;","handlingStrategy":"validation","validationCode":"fn loader_registered(path: &str, loaders: &HashMap<String, String>) -> Result<(), String> {\n    match path.split_once(':') {\n        Some((protocol, _)) if loaders.contains_key(protocol) => Ok(()),\n        Some((protocol, _)) => Err(format!(\"no loader registered for protocol '{protocol}'\")),\n        None => Err(format!(\"path {path:?} has no 'protocol:' prefix\")),\n    }\n}","typeGuard":null,"tryCatchPattern":"match load_protocol_path(p, &loaders) {\n    Err(e) if e.to_string().starts_with(\"No document loader for\") => {\n        eprintln!(\"Skipping {p}: no loader configured\");\n    }\n    other => other?,\n}","preventionTips":["Keep loader keys and path prefixes consistent (e.g. always 'https', never 'http').","Validate document lists against configured loaders before syncing.","Register a default/error loader for unknown protocols in shared config.","Grep docs indexes for 'scheme:' prefixes that lack loader entries."],"tags":["loader","configuration","protocol","missing-mapping"],"backgroundTag":"resource-not-found","analyzedSha":"82976d349ad97ac9aae0655ad631dace5e2a6385","analyzedAt":"2026-09-09T18:33:06.139Z","contentChangedAt":"2026-09-09T18:33:06.139Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}