flipped-aurora/gin-vue-admin · error

自动代码回滚索引无效: %d

Error message

自动代码回滚索引无效: %d

What it means

During rollback of an auto-code file transaction, each applied file index is validated against the task's file list. If an index in `applied` is negative or beyond the number of tracked files, rollback aborts with this error instead of touching the filesystem. This is an internal invariant guard — it should never fire through normal API use, only when the applied-index bookkeeping is corrupted or rollback is called with a slice built against a different task.

Source

Thrown at server/service/system/auto_code_task.go:219

	}
	if exists != file.Existed || (file.Existed && currentHash != file.BeforeHash) {
		return false, fmt.Errorf("%w: %s", errAutoCodeFileConflict, file.TargetPath)
	}
	if err = os.MkdirAll(filepath.Dir(file.TargetPath), 0o755); err != nil {
		return false, fmt.Errorf("创建目标目录 %s 失败: %w", filepath.Dir(file.TargetPath), err)
	}
	if err = os.Rename(file.StagedPath, file.TargetPath); err != nil {
		return false, fmt.Errorf("原子发布 %s 失败: %w", file.TargetPath, err)
	}
	file.StagedPath = ""
	return true, nil
}

func (task *autoCodeFileTask) rollback(applied []int) error {
	for i := len(applied) - 1; i >= 0; i-- {
		index := applied[i]
		if index < 0 || index >= len(task.files) {
			return fmt.Errorf("自动代码回滚索引无效: %d", index)
		}
		file := &task.files[index]
		currentHash, exists, err := hashAutoCodeTarget(file.TargetPath)
		if err != nil {
			return err
		}
		if file.Existed && exists && currentHash == file.BeforeHash {
			continue
		}
		if !exists || currentHash != file.AfterHash {
			return fmt.Errorf("%w: %s", errAutoCodeFileConflict, file.TargetPath)
		}
		if !file.Existed {
			if err = os.Remove(file.TargetPath); err != nil && !errors.Is(err, fs.ErrNotExist) {
				return fmt.Errorf("删除新建文件 %s 失败: %w", file.TargetPath, err)
			}
			continue
		}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Audit any custom autoCodeFilePublisher / apply logic so it only appends indexes returned by `for index := range task.files` of the same task instance
  2. Ensure nothing mutates task.files between apply and rollback (rollback runs inside commitAutoCodeFileTask synchronously; do not share the task across goroutines)
  3. If hit in stock gin-vue-admin code, report it — the invariant is broken upstream, and the joined error will show the original cause plus 回滚自动代码文件失败

Example fix

// before (hypothetical custom publisher returning a stale index)
applied = append(applied, staleIndex)
// after
for index := range task.files {
    if task.files[index].Kind == kind {
        applied = append(applied, index)
    }
}
Defensive patterns

Strategy: validation

Validate before calling

func validateApplied(applied []int, files int) error {
    for _, i := range applied {
        if i < 0 || i >= files {
            return fmt.Errorf("applied index %d out of range [0,%d)", i, files)
        }
    }
    return nil
}

Type guard

func validIndex(i, n int) bool { return i >= 0 && i < n }

Try / catch

err := task.rollback(applied)
if err != nil {
    // joined error includes 回滚自动代码文件失败
    if errors.Is(err, errAutoCodeFileConflict) { /* reconcile files */ }
    log.Printf("rollback failed: %v", err)
}

Prevention

When it happens

Trigger: Calling autoCodeFileTask.rollback(applied) with an `applied` slice that contains an out-of-range index: either produced by a buggy `apply`/publisher implementation, a task whose `files` slice was mutated after apply, or reusing indexes from another task instance.

Common situations: Custom modifications to the auto-code commit pipeline, concurrent mutation of task.files, or tests calling rollback directly with hand-built index slices.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/529b2206598425da. Report an issue: GitHub.