siyuan-note/siyuan · error

invalid reorder position [%s]

Error message

invalid reorder position [%s]

What it means

validateReorderArgs only accepts the literal strings "before" or "after" as the reorder position. Any other value — including "", "Before", "top", or "above" — produces this formatted error naming the offending position. The position determines whether the sources are inserted before or after the target document in the custom sibling order.

Source

Thrown at kernel/model/file.go:2722

		fileTreeSortLock.Unlock()
		return ret, writeErr
	}
	fileTreeSortLock.Unlock()

	ret.Changed = true
	ret.Notebook = box.ID
	ret.ParentPath = parentPath
	IncSync()
	pushFiletreeSortChanged(sortIDs)
	return
}

func validateReorderArgs(sourceIDs []string, targetID, position string) error {
	if 1 > len(sourceIDs) {
		return errors.New("source IDs must not be empty")
	}
	if "before" != position && "after" != position {
		return fmt.Errorf("invalid reorder position [%s]", position)
	}
	seen := map[string]struct{}{}
	for _, sourceID := range sourceIDs {
		if sourceID == targetID {
			return fmt.Errorf("target ID [%s] must not be included in source IDs", targetID)
		}
		if _, ok := seen[sourceID]; ok {
			return fmt.Errorf("duplicate source ID [%s]", sourceID)
		}
		seen[sourceID] = struct{}{}
	}
	return nil
}

func isSortableDocument(tree *treenode.BlockTree) bool {
	return nil != tree && tree.ID == tree.RootID && "d" == tree.Type && !IsBoxDoc(tree.BoxID, tree.RootID)
}

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Pass exactly "before" or "after" as the position argument
  2. Normalize/validate the position in the caller: p := strings.ToLower(p); if p != "before" && p != "after" { p = "before" }
  3. Check the plugin or script for renamed position constants and align them with the kernel API

Example fix

// before
err := model.ReorderDocs(sourceIDs, targetID, "above") // rejected
// after
position := "before"
if dropAfterTarget {
    position = "after"
}
err := model.ReorderDocs(sourceIDs, targetID, position)
Defensive patterns

Strategy: validation

Validate before calling

if position != "before" && position != "after" {
    return fmt.Errorf("position must be before or after, got %q", position)
}

Type guard

func isValidPosition(p string) bool { return p == "before" || p == "after" }

Try / catch

if !isValidPosition(position) {
    position = "before" // or surface a validation error
}

Prevention

When it happens

Trigger: Calling ReorderDocs(sourceIDs, targetID, "above") or any string other than exactly "before"/"after"; passing an unvalidated UI dropdown value or an empty position string from plugin/scripted API calls; case mismatch such as "Before".

Common situations: Hard-coded position constants that don't match the kernel's accepted enum; older client code using different drag-direction vocabulary; dynamically computed positions that end up empty when drag metadata is missing.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/cf06356717991a01. Report an issue: GitHub.