{"record":{"id":"370574b8b252f2cb","repo":"AlistGo/alist","slug":"pattern-must-contain-exactly-one-chunk-token-chu","errorCode":null,"errorMessage":"pattern must contain exactly one chunk token: {chunk} or {chunk:N}","messagePattern":"pattern must contain exactly one chunk token: (.+?) or (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/chunker/util.go","lineNumber":142,"sourceCode":"\tswitch nameMagicCount {\n\tcase 0:\n\t\treturn 0, 0, errors.New(\"pattern must contain one name token: {name}\")\n\tcase 1:\n\tdefault:\n\t\treturn 0, 0, errors.New(\"pattern must contain exactly one name token: {name}\")\n\t}\n\tstart = strings.Index(pattern, \"{name}\")\n\treturn start, start + len(\"{name}\"), nil\n}\n\nfunc parseChunkToken(pattern string) (start, end, width int, err error) {\n\tchunkMatches := chunkTokenRegexp.FindAllStringSubmatchIndex(pattern, -1)\n\tswitch len(chunkMatches) {\n\tcase 0:\n\t\treturn 0, 0, 0, errors.New(\"pattern must contain one chunk token: {chunk} or {chunk:N}\")\n\tcase 1:\n\tdefault:\n\t\treturn 0, 0, 0, errors.New(\"pattern must contain exactly one chunk token: {chunk} or {chunk:N}\")\n\t}\n\tmatch := chunkMatches[0]\n\tstart = match[0]\n\tend = match[1]\n\tif match[2] >= 0 && match[3] >= 0 {\n\t\twidth, err = strconv.Atoi(pattern[match[2]:match[3]])\n\t\tif err != nil || width <= 0 {\n\t\t\treturn 0, 0, 0, errors.New(\"chunk width in {chunk:N} must be a positive integer\")\n\t\t}\n\t}\n\treturn start, end, width, nil\n}\n\nfunc (d *Chunker) makeChunkName(filePath string, chunkNo int, xactID string) string {\n\tdir, baseName := path.Split(filePath)\n\tname := fmt.Sprintf(d.dataNameFmt, baseName, chunkNo+d.StartFrom)\n\tif xactID != \"\" {\n\t\tname += fmt.Sprintf(tempSuffixFormat, xactID)","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/chunker/util.go#L124-L160","documentation":"parseChunkToken reports this when the chunk name format contains two or more {chunk} or {chunk:N} tokens. Exactly one chunk token is allowed because the compiled printf format has a single numeric verb and the reverse regexp must map each chunk file to one number.","triggerScenarios":"Patterns like '{name}_{chunk}_{chunk:03}' or '{name}-{chunk:N}-{chunk}'. Detected via chunkTokenRegexp.FindAllStringSubmatchIndex returning more than one match; fails at init.","commonSituations":"Attempting to repeat the chunk number for readability; merging two templates; trying to encode chunk/total (e.g. '{chunk:02}-of-{chunk:02}') which the format language does not support.","solutions":["Keep a single {chunk} or {chunk:N} token","For chunk-of-total style names, note total is not expressible — use fixed width {chunk:N} only"],"exampleFix":"// before\nchunk_name_format: {name}_{chunk:02}_of_{chunk:02}\n// after\nchunk_name_format: {name}_{chunk:02}","handlingStrategy":"validation","validationCode":"var chunkToken = regexp.MustCompile(`\\{chunk(:[0-9]+)?\\}`)\nif n := len(chunkToken.FindAllString(f, -1)); n != 1 {\n    return fmt.Errorf(\"expected exactly 1 chunk token, found %d in %q\", n, f)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Count all chunk token variants ({chunk} and {chunk:N}) together when validating","Prefer a small allowlist of known-good templates over free-form input"],"tags":["chunker","configuration","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}