AlistGo/alist · error

the line '%s' is not a multiple of 2

Error message

the line '%s' is not a multiple of 2

What it means

The url_tree driver builds a file hierarchy from an indented text structure where each nesting level is exactly two spaces. When a line's leading-space count is odd (indent%2 != 0), the tree parser cannot compute a level and aborts tree construction with this per-line error.

Source

Thrown at drivers/url_tree/util.go:51

 * url8
 */
// if there are no name, use the last segment of url as name
func BuildTree(text string, headSize bool) (*Node, error) {
	lines := strings.Split(text, "\n")
	var root = &Node{Level: -1, Name: "root"}
	stack := []*Node{root}
	for _, line := range lines {
		// calculate indent
		indent := 0
		for i := 0; i < len(line); i++ {
			if line[i] != ' ' {
				break
			}
			indent++
		}
		// if indent is not a multiple of 2, it is an error
		if indent%2 != 0 {
			return nil, fmt.Errorf("the line '%s' is not a multiple of 2", line)
		}
		// calculate level
		level := indent / 2
		line = strings.TrimSpace(line[indent:])
		// if the line is empty, skip
		if line == "" {
			continue
		}
		// if level isn't greater than the level of the top of the stack
		// it is not the child of the top of the stack
		for level <= stack[len(stack)-1].Level {
			// pop the top of the stack
			stack = stack[:len(stack)-1]
		}
		// if the line is a folder
		if isFolder(line) {
			// create a new node
			node := &Node{

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Re-indent the whole url_structure using only multiples of two spaces per level (0, 2, 4, 6 ...).
  2. Replace all tabs with spaces in the config before saving.
  3. Re-generate the structure with StringifyTree output as a canonical reference — it always emits two spaces per level.

Example fix

// before
root:
  a.txt http://x/a
   b.txt http://x/b   // 3 spaces -> error

// after
root:
  a.txt http://x/a
  b.txt http://x/b
Defensive patterns

Strategy: validation

Validate before calling

func validateIndentation(structure string) error {
    for _, line := range strings.Split(structure, "\n") {
        indent := 0
        for indent < len(line) && line[indent] == ' ' { indent++ }
        if indent%2 != 0 {
            return fmt.Errorf("line %q has odd indent", line)
        }
    }
    return nil
}

Try / catch

if _, err := BuildTree(structure, headSize); err != nil {
    if strings.Contains(err.Error(), "not a multiple of 2") { /* fix indentation in config */ }
    return err
}

Prevention

When it happens

Trigger: Any line in the url_structure config whose indentation is 1, 3, 5, ... spaces — e.g. a tab converted partially, or manual alignment with an odd number of spaces.

Common situations: Copy-pasting tree text from editors with tab expansion, mixing tabs and spaces, or hand-editing the structure and adding a stray space. Fails at storage Init, so the mount is rejected outright.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/0c944111788c5540. Report an issue: GitHub.