{"record":{"id":"3099884400a73da8","repo":"AlistGo/alist","slug":"name-token-must-come-before-chunk-token","errorCode":null,"errorMessage":"name token must come before chunk token","messagePattern":"name token must come before chunk token","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/chunker/util.go","lineNumber":86,"sourceCode":"\t}\n\treturn paths\n}\n\nfunc (d *Chunker) setChunkNameFormat(pattern string) error {\n\tif dir, _ := path.Split(pattern); dir != \"\" {\n\t\treturn errors.New(\"directory separator prohibited\")\n\t}\n\n\tnameStart, nameEnd, err := parseNameToken(pattern)\n\tif err != nil {\n\t\treturn err\n\t}\n\tchunkStart, chunkEnd, chunkWidth, err := parseChunkToken(pattern)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif nameStart > chunkStart {\n\t\treturn errors.New(\"name token must come before chunk token\")\n\t}\n\n\treDigits := \"[0-9]+\"\n\tif chunkWidth > 0 {\n\t\treDigits = fmt.Sprintf(\"[0-9]{%d,}\", chunkWidth)\n\t}\n\treDataOrCtrl := fmt.Sprintf(\"(?:(%s)|_(%s))\", reDigits, ctrlTypeRegStr)\n\n\tbeforeName := pattern[:nameStart]\n\tbetween := pattern[nameEnd:chunkStart]\n\tafterChunk := pattern[chunkEnd:]\n\n\tstrRegex := fmt.Sprintf(\n\t\t\"^%s(.+?)%s%s%s(?:%s|%s)?$\",\n\t\tregexp.QuoteMeta(beforeName),\n\t\tregexp.QuoteMeta(between),\n\t\treDataOrCtrl,\n\t\tregexp.QuoteMeta(afterChunk),","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/chunker/util.go#L68-L104","documentation":"In the chunker chunk name format, the {name} token must appear before the {chunk} token. The driver compiles the pattern into a printf format (dataNameFmt) and a reverse-matching regexp that both assume name-then-chunk ordering; a pattern with {chunk} first would break reconstruction of the original file name.","triggerScenarios":"Setting chunk_name_format to something like '{chunk:03}_{name}' or 'part-{chunk}-of-{name}' where parseNameToken's start index is greater than parseChunkToken's start index. Fails during setChunkNameFormat at storage init.","commonSituations":"Users wanting the chunk number first for sorting in listings; templates copied from another tool with different token rules; typos swapping token order.","solutions":["Reorder the pattern so {name} comes first: '{name}_{chunk:03}'","If chunk-number-first sorting is desired, use a fixed-width chunk token after the name and sort by it, or rely on listing options instead","Validate the pattern in a scratch program or test before saving the storage config"],"exampleFix":"// before\nchunk_name_format: {chunk:03}_{name}\n// after\nchunk_name_format: {name}_{chunk:03}","handlingStrategy":"validation","validationCode":"nameIdx := strings.Index(f, \"{name}\")\nchunkIdx := strings.Index(f, \"{chunk}\")\nif nameIdx == -1 || chunkIdx == -1 || nameIdx > chunkIdx {\n    return fmt.Errorf(\"format must contain {name} before {chunk}: %q\", f)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint the template order whenever users can edit chunk_name_format","Include the order rule in any config UI hint text"],"tags":["chunker","configuration","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}