{"record":{"id":"a30da83770464dca","repo":"XTLS/Xray-core","slug":"invalid-geodata-asset-file","errorCode":null,"errorMessage":"invalid geodata asset file: ","messagePattern":"invalid geodata asset file: ","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/geodata.go","lineNumber":23,"sourceCode":"\n\t\"github.com/robfig/cron/v3\"\n\t\"github.com/xtls/xray-core/app/geodata\"\n\t\"github.com/xtls/xray-core/common/errors\"\n\t\"github.com/xtls/xray-core/common/platform/filesystem\"\n\t\"google.golang.org/protobuf/proto\"\n)\n\ntype GeodataAssetConfig struct {\n\tURL  string `json:\"url\"`\n\tFile string `json:\"file\"`\n}\n\nfunc (c *GeodataAssetConfig) Build() (*geodata.Asset, error) {\n\tif err := validateHTTPS(c.URL); err != nil {\n\t\treturn nil, errors.New(\"invalid geodata asset url: \", c.URL).Base(err)\n\t}\n\tif _, err := filesystem.StatAsset(c.File); err != nil {\n\t\treturn nil, errors.New(\"invalid geodata asset file: \", c.File).Base(err)\n\t}\n\treturn &geodata.Asset{\n\t\tUrl:  c.URL,\n\t\tFile: c.File,\n\t}, nil\n}\n\nfunc validateHTTPS(s string) error {\n\tu, err := url.ParseRequestURI(s)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif u.Scheme != \"https\" || u.Host == \"\" {\n\t\treturn errors.New(\"scheme must be https\")\n\t}\n\treturn nil\n}\n","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/geodata.go#L5-L41","documentation":"Thrown by GeodataAssetConfig.Build when filesystem.StatAsset fails for the asset's file field, meaning the asset filename cannot be stat'ed in the asset location (typically the Xray resource directory). Every asset entry pairs a download URL with the local file name it maps to; the file must resolve in the asset filesystem. The underlying stat error is chained as the base cause.","triggerScenarios":"Setting geodata.assets[].file to an empty string, a path with invalid characters, a subdirectory that does not exist in the asset dir, or a name that the platform-specific asset loader cannot resolve.","commonSituations":"Omitting the file field (defaults to empty string, which fails stat); using a full filesystem path instead of a bare asset name; name mismatch between the file field and the geosite/geoip filename expected later; missing XRAY_LOCATION_ASSET directory.","solutions":["Set file to a plain asset filename like \"geosite.dat\" or \"geoip.dat\" matching what the URL downloads","Verify XRAY_LOCATION_ASSET (default: the executable's directory or a system location) exists and is readable","Do not use directory paths or empty strings for file"],"exampleFix":"// before\n{ \"url\": \"https://example/geosite.dat\", \"file\": \"/etc/xray/geosite.dat\" }\n// after\n{ \"url\": \"https://example/geosite.dat\", \"file\": \"geosite.dat\" }","handlingStrategy":"validation","validationCode":"// Check the asset file name is a bare, non-empty filename\nif asset.File == \"\" || strings.ContainsAny(asset.File, \"/\\\\\") {\n\treturn fmt.Errorf(\"asset file must be a non-empty bare filename\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use bare filenames like geosite.dat, never absolute paths","Ensure XRAY_LOCATION_ASSET points to an existing readable directory before startup"],"tags":["xray","config","geodata","filesystem","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}