BigPizzaV3/CodexPlusPlus · error · anyhow::Error
仓库 owner/name 只能包含字母、数字、`.`、`_`、`-`
Error message
仓库 owner/name 只能包含字母、数字、`.`、`_`、`-`
What it means
normalize_repo then applies is_safe_repo_segment to owner and name, allowing only ASCII alphanumerics, '.', '_' and '-'. This bail means one of them contains other characters (spaces, slashes, Unicode) that would break repo URL construction or path safety.
Solutions
- owner/name 只填裸段:如 owner="anthropic",name="skills",不要填 URL
- 提交前用正则 ^[A-Za-z0-9._-]+$ 预校验两个字段
- 若是 URL,先按 '/' 分段取出最后两段再分别作为 owner/name 传入
Example fix
// before
state.upsert_repo(&repo_with_owner "https://github.com/anthropic/skills");
// after
let owner = "anthropic"; // 从 URL parse 出的裸段
let name = "skills";
assert!(owner.chars().all(|c| c.is_ascii_alphanumeric() || matches!(c, '.'|'_'|'-')));
state.upsert_repo(&SkillRepo { owner: owner.into(), name: name.into(), .. })?; Defensive patterns
Strategy: validation
Validate before calling
use regex::Regex;
fn is_safe_repo_segment(s: &str) -> bool {
Regex::new(r"^[A-Za-z0-9._-]+$").unwrap().is_match(s)
}
// 提交前:if !is_safe_repo_segment(owner) || !is_safe_repo_segment(name) { bail!("非法 owner/name") } Try / catch
match state.upsert_repo(&repo) {
Err(e) if e.to_string().contains("只能包含字母、数字") => eprintln!("owner/name 含非法字符:{}", e),
other => other?,
} Prevention
- 用户输入 URL 时先解析出裸 owner/name 段再入库
- 输入框做实时字符白名单校验
- 避免直接粘贴带协议前缀的 GitHub 地址到 owner 字段
When it happens
Trigger: 调用 upsert_repo 时 owner 或 name 含有字母数字与 ._- 之外的字符,如空格、斜杠 `/`、中文、`@`、`:` 等。
Common situations: 用户把完整 URL(如 https://github.com/owner/repo)直接填进 owner 字段,带入 `://` 和 `/`;输入了带空格或大小写外符号的仓库名;从其他平台复制仓库名。
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- 仓库 owner 和 name 不能为空
- 主题包必须是 32 MiB 以内的普通 ZIP 文件
- 请填写 API 的模型名称
- 官方混合 API 不应在 auth.json 中保存 OPENAI_API_KEY。请清理此供应商的…
- 请填写 API 的模型名称
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@b1ed92e5e4 (2026-09-19).
Data as JSON: /api/errors/ba11f21f55766bd1.
Report an issue: GitHub.
Appendix: source
Thrown at crates/codex-plus-core/src/skills.rs:601
}
fn normalize_repo(repo: SkillRepo) -> anyhow::Result<SkillRepo> {
let owner = repo.owner.trim().to_string();
let name = repo.name.trim().to_string();
let branch = {
let trimmed = repo.branch.trim();
if trimmed.is_empty() {
default_branch()
} else {
trimmed.to_string()
}
};
let subdir = repo.subdir.trim().trim_matches('/').to_string();
if owner.is_empty() || name.is_empty() {
anyhow::bail!("仓库 owner 和 name 不能为空");
}
if !is_safe_repo_segment(&owner) || !is_safe_repo_segment(&name) {
anyhow::bail!("仓库 owner/name 只能包含字母、数字、`.`、`_`、`-`");
}
Ok(SkillRepo {
owner,
name,
branch,
subdir,
enabled: repo.enabled,
})
}
fn is_safe_repo_segment(value: &str) -> bool {
!value.is_empty()
&& value
.chars()
.all(|c| c.is_ascii_alphanumeric() || matches!(c, '.' | '_' | '-'))
}
/// skill id 直接参与拼路径,必须挡住 `..` 和分隔符。View on GitHub (pinned to b1ed92e5e4)