{"record":{"id":"439a8c87fb997f67","repo":"siyuan-note/siyuan","slug":"invalid-package-name-s-439a8c","errorCode":null,"errorMessage":"invalid package name: %s","messagePattern":"invalid package name: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/bazaar/rating.go","lineNumber":435,"sourceCode":"\t\treturn nil, err\n\t}\n\tif 200 != resp.StatusCode {\n\t\treturn nil, fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode)\n\t}\n\n\tret, err = parseBazaarRatingRegion(buf.Bytes())\n\treturn\n}\n\nfunc parseBazaarRatingRegion(data []byte) (ret map[string]bazaarRatingDistribution, err error) {\n\traw := map[string]json.RawMessage{}\n\tif err = json.Unmarshal(data, &raw); nil != err {\n\t\treturn nil, err\n\t}\n\tret = make(map[string]bazaarRatingDistribution, len(raw))\n\tfor packageName, rawDistribution := range raw {\n\t\tif !IsValidPackageName(packageName) {\n\t\t\treturn nil, fmt.Errorf(\"invalid package name: %s\", packageName)\n\t\t}\n\t\tvar values []int64\n\t\tif err = json.Unmarshal(rawDistribution, &values); nil != err {\n\t\t\treturn nil, err\n\t\t}\n\t\tif 5 != len(values) {\n\t\t\treturn nil, fmt.Errorf(\"invalid rating distribution length for package: %s\", packageName)\n\t\t}\n\t\tdistribution := bazaarRatingDistribution(values)\n\t\tif !validBazaarRatingDistribution(distribution) {\n\t\t\treturn nil, fmt.Errorf(\"invalid rating distribution for package: %s\", packageName)\n\t\t}\n\t\tret[packageName] = distribution\n\t}\n\treturn\n}\n\nfunc mergeBazaarRatingRegions(regions [bazaarRatingRegionCount]bazaarRatingRegionResult) map[string]*PackageRating {","sourceCodeStart":417,"sourceCodeEnd":453,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/9f775e8a12daef8255556097396f9b2739078892/kernel/bazaar/rating.go#L417-L453","documentation":"parseBazaarRatingRegion unmarshals the region file into a map of package name -> raw rating distribution and validates each key with IsValidPackageName, which enforces a safe cross-platform directory name (1-255 printable UTF-8 bytes, no leading dot/space, no trailing dot/space, no '..', no <>&'\":/\\|?*, not a Windows reserved name). A key that fails this check aborts the whole region file parse with this error. This guards against corrupt or malicious CDN data being used as install directory names.","triggerScenarios":"Calling fetchBazaarRatingRegion / parseBazaarRatingRegion on a region JSON whose top-level object contains a key like \"\", \".hidden\", \"a/b\", \"CON\", \"pkg \", or a >255-byte name — typically from a tampered, hand-edited, or wrongly generated ratings file, or an old-format file where keys were repo URLs like \"user/repo@version\" instead of package names.","commonSituations":"The rating stat pipeline was changed to emit repo slugs or IDs instead of package names; someone hand-edited the CDN JSON; a stale ratings file from a previous schema is cached and served; the region files were regenerated from a source containing invalid placeholder names.","solutions":["Log the offending package name from the error and fix the entry at the source (the ratings generation pipeline or the CDN file)","If the file is an old schema (repo-URL keys), regenerate the region files with plain package names as keys","Validate the ratings JSON with the same rules as IsValidPackageName before publishing it to the CDN","If serving cached data, clear the stale bucket so the corrected file is fetched"],"exampleFix":"// before (in ratings source data)\n{\"siyuan-note/sample-plugin-md\": [1,2,3,4,5]}  // slash makes it invalid\n// after\n{\"sample-plugin-md\": [1,2,3,4,5]}","handlingStrategy":"validation","validationCode":"for name := range rawRatings {\n    if !bazaar.IsValidPackageName(name) {\n        return fmt.Errorf(\"region file has invalid package name: %q\", name)\n    }\n}","typeGuard":null,"tryCatchPattern":"dist, err := parseBazaarRatingRegion(data)\nif err != nil && strings.HasPrefix(err.Error(), \"invalid package name\") {\n    log.Warnf(\"skipping malformed ratings region file: %v\", err)\n    return map[string]bazaarRatingDistribution{}\n}","preventionTips":["Publish ratings files keyed by plain package names, never repo slugs or paths","Run the same IsValidPackageName rules in the ratings generation pipeline before upload","Never hand-edit CDN rating JSON; regenerate from source data","Pin/validate the region file schema version"],"tags":["bazaar","ratings","validation","json"],"backgroundTag":"invalid-identifier-format","analyzedSha":"9f775e8a12daef8255556097396f9b2739078892","analyzedAt":"2026-09-19T03:17:15.984Z","contentChangedAt":"2026-09-19T03:17:15.984Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}