AlistGo/alist · error · NotFolder

not a folder

Error message

not a folder

What it means

NotFolder is a sentinel in internal/errs/object.go stating the resolved object exists but is not a directory. Operations that require a directory target (listing it, mkdir inside it, moving something into it) return it when the path names a file.

Source

Thrown at internal/errs/object.go:11

package errs

import (
	"errors"

	pkgerr "github.com/pkg/errors"
)

var (
	ObjectNotFound = errors.New("object not found")
	NotFolder      = errors.New("not a folder")
	NotFile        = errors.New("not a file")
)

func IsObjectNotFound(err error) bool {
	return errors.Is(pkgerr.Cause(err), ObjectNotFound)
}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Check the object type at that path and use the correct target (the actual folder)
  2. Rename or delete the conflicting file that occupies the folder name
  3. Invalidate the cached meta for that path if the remote was changed externally
  4. Add a pre-check on model.Obj.IsDir() before directory-requiring calls

Example fix

// before
err := fs.Mkdir(ctx, "/data/file.txt/newdir")

// after
obj, err := op.Get(ctx, "/data/file.txt")
if err == nil && !obj.IsDir() {
    return errs.NotFolder
}
Defensive patterns

Strategy: type-guard

Validate before calling

// check the target is a directory before directory-requiring ops
if obj, err := op.Get(ctx, dst); err == nil && !obj.IsDir() {
    return errs.NotFolder
}

Type guard

func requiresFolder(obj model.Obj) error {
    if !obj.IsDir() { return errs.NotFolder }
    return nil
}

Try / catch

if err := fs.MakeDir(ctx, path); err != nil {
    if errors.Is(errors.Cause(err), errs.NotFolder) {
        // a file occupies the folder name — surface a clear message
    }
}

Prevention

When it happens

Trigger: Listing a path that is a regular file; creating a folder under a path that is actually a file (Mkdir); renaming/moving a file into a destination that is a file; upload with a directory component that resolves to an existing file.

Common situations: A file and intended folder share the same name (e.g. 'movie' file vs 'movie/' directory); case-insensitive storages masking a name collision; stale cache saying a path is a folder after it was replaced by a file; FTP clients issuing CWD against a file.

Related errors


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