{"record":{"id":"c9650ff7b0b8423f","repo":"AlistGo/alist","slug":"invalid-format-s","errorCode":null,"errorMessage":"invalid format: %s","messagePattern":"invalid format: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/github_releases/util.go","lineNumber":49,"sourceCode":"// 解析挂载结构\nfunc (d *GithubReleases) ParseRepos(text string) ([]MountPoint, error) {\n\tlines := strings.Split(text, \"\\n\")\n\tpoints := make([]MountPoint, 0)\n\tfor _, line := range lines {\n\t\tline = strings.TrimSpace(line)\n\t\tif line == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tparts := strings.Split(line, \":\")\n\t\tpath, repo := \"\", \"\"\n\t\tif len(parts) == 1 {\n\t\t\tpath = \"/\"\n\t\t\trepo = parts[0]\n\t\t} else if len(parts) == 2 {\n\t\t\tpath = fmt.Sprintf(\"/%s\", strings.Trim(parts[0], \"/\"))\n\t\t\trepo = parts[1]\n\t\t} else {\n\t\t\treturn nil, fmt.Errorf(\"invalid format: %s\", line)\n\t\t}\n\n\t\tpoints = append(points, MountPoint{\n\t\t\tPoint:    path,\n\t\t\tRepo:     repo,\n\t\t\tRelease:  nil,\n\t\t\tReleases: nil,\n\t\t})\n\t}\n\td.points = points\n\treturn points, nil\n}\n\n// 获取下一级目录\nfunc GetNextDir(wholePath string, basePath string) string {\n\tbasePath = fmt.Sprintf(\"%s/\", strings.TrimRight(basePath, \"/\"))\n\tif !strings.HasPrefix(wholePath, basePath) {\n\t\treturn \"\"","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/github_releases/util.go#L31-L67","documentation":"Thrown while parsing the github_releases driver's mount-point configuration. Each non-empty config line must be either 'repo' (mounted at /) or 'path:repo' (path first, repo second). A line containing two or more ':' characters does not match either shape and is rejected with 'invalid format: <line>'.","triggerScenarios":"Calling the mount-point parser (init/read of github_releases driver config) with a line like 'a:b:c' or a repo URL containing a colon such as 'https://github.com:user/repo' or 'media:github.com/org/repo'. strings.Split(line, ':') yields >2 parts and the else-branch returns the error.","commonSituations":"User enters a full HTTPS clone URL instead of owner/repo; user writes 'path:owner:repo' expecting multiple segments; stray colon from copy-pasting 'git@github.com:org/repo.git' SSH URLs; trailing 'driveletter:-style' artifacts on Windows configs.","solutions":["Use exactly one colon: '/mount/path:owner/repo', or a bare 'owner/repo' for root mount","Replace full URLs with the owner/repo form, e.g. 'github.com/org/repo' -> 'org/repo' (strip scheme and host)","Remove SSH-style prefixes like 'git@github.com:' before the owner/repo part"],"exampleFix":"// before\nmount: https://github.com:443/alistgo/alist\n// invalid format: https://github.com:443/alistgo/alist\n\n// after\n/: alistgo/alist\n/media: alistgo/alist","handlingStrategy":"validation","validationCode":"func validMountLine(line string) bool {\n  parts := strings.Split(line, \":\")\n  if len(parts) > 2 { return false }\n  repo := parts[len(parts)-1]\n  seg := strings.Split(strings.Trim(repo, \"/\"), \"/\")\n  return len(seg) == 2 && seg[0] != \"\" && seg[1] != \"\" && !strings.Contains(repo, \"://\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use 'path:owner/repo' or bare 'owner/repo' only — never full URLs","Validate mount config lines in CI before applying storage settings"],"tags":["github-releases","config","validation","mount"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}