{"record":{"id":"97e921f82c6ab3cc","repo":"AlistGo/alist","slug":"pattern-must-contain-exactly-one-name-token-name","errorCode":null,"errorMessage":"pattern must contain exactly one name token: {name}","messagePattern":"pattern must contain exactly one name token: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/chunker/util.go","lineNumber":129,"sourceCode":"\tif chunkWidth > 0 {\n\t\tfmtDigits = fmt.Sprintf(\"%%0%dd\", chunkWidth)\n\t}\n\td.dataNameFmt = strings.ReplaceAll(beforeName, \"%\", \"%%\") +\n\t\t\"%s\" +\n\t\tstrings.ReplaceAll(between, \"%\", \"%%\") +\n\t\tfmtDigits +\n\t\tstrings.ReplaceAll(afterChunk, \"%\", \"%%\")\n\treturn nil\n}\n\nfunc parseNameToken(pattern string) (start, end int, err error) {\n\tnameMagicCount := strings.Count(pattern, \"{name}\")\n\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 {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/chunker/util.go#L111-L147","documentation":"parseNameToken reports this when the chunk name format contains two or more {name} tokens. Exactly one is required: the driver builds a printf format string (%s for the name) and a regexp to reverse-match chunk files, and multiple name tokens are ambiguous.","triggerScenarios":"A chunk_name_format like '{name}-{name}_{chunk:03}' or '{name}/{name}_{chunk}' (after removing separators). Raised in setChunkNameFormat at init time.","commonSituations":"Copy-paste concatenation of templates; attempting to simulate name+extension separately (e.g. '{name}.{name}'); editing an existing pattern and accidentally duplicating the token.","solutions":["Leave exactly one {name} token in the pattern","If you wanted name and extension split, note that {name} already denotes the full base name including extension — use it once"],"exampleFix":"// before\nchunk_name_format: {name}.{name}_{chunk:03}\n// after\nchunk_name_format: {name}_{chunk:03}","handlingStrategy":"validation","validationCode":"if strings.Count(f, \"{name}\") != 1 {\n    return fmt.Errorf(\"chunk name format must contain exactly one {name} token: %q\", f)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use strings.Count rather than Index when validating, so duplicates are caught","Run the driver's own setChunkNameFormat in a dry-run/test before deploying config"],"tags":["chunker","configuration","validation"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}