AlistGo/alist · error
unable to convert dir to mega n
Error message
unable to convert dir to mega n
What it means
Mega driver List was called with a dir that is not the driver's *MegaNode concrete type, so the children cannot be enumerated. The preceding log line ('can't convert: %+v') dumps the offending object. Root cause is the same class as the other Mega conversion errors: the model.Obj came from outside this driver's own object graph.
Source
Thrown at drivers/mega/driver.go:78
for i := range nodes {
n := nodes[i]
if n.GetType() != mega.FILE && n.GetType() != mega.FOLDER {
continue
}
if _, ok := fn[n.GetName()]; !ok {
fn[n.GetName()] = &MegaNode{n}
} else if sameNameObj := fn[n.GetName()]; (&MegaNode{n}).ModTime().After(sameNameObj.ModTime()) {
fn[n.GetName()] = &MegaNode{n}
}
}
res := make([]model.Obj, 0)
for _, v := range fn {
res = append(res, v)
}
return res, nil
}
log.Errorf("can't convert: %+v", dir)
return nil, fmt.Errorf("unable to convert dir to mega n")
}
func (d *Mega) GetRoot(ctx context.Context) (model.Obj, error) {
n := d.c.FS.GetRoot()
log.Debugf("mega root: %+v", *n)
return &MegaNode{n}, nil
}
func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
if node, ok := file.(*MegaNode); ok {
//down, err := d.c.NewDownload(n.Node)
//if err != nil {
// return nil, fmt.Errorf("open download file failed: %w", err)
//}
size := file.GetSize()
resultRangeReader := func(ctx context.Context, httpRange http_range.Range) (io.ReadCloser, error) {View on GitHub (pinned to 843d9dc814)
Solutions
- Always obtain the dir from d.GetRoot() or a previous List result of the same driver instance
- Use GetRoot()+path resolution through the driver itself instead of synthesizing objects
- In frameworks, route through driver.Get(path) to re-materialize a *MegaNode before List
- For tests, wrap real mega nodes: construct MegaNode{n} from d.c.FS.Get(...)
Example fix
// before
if node, ok := dir.(*MegaNode); ok {
/* list children */
}
log.Errorf("can't convert: %+v", dir)
return nil, fmt.Errorf("unable to convert dir to mega n")
// after (fail fast with actionable info)
node, ok := dir.(*MegaNode)
if !ok {
log.Errorf("can't convert dir (type %T) to *MegaNode; re-fetch via Get(path)", dir)
return nil, fmt.Errorf("unable to convert dir to mega n (got %T)", dir)
} Defensive patterns
Strategy: type-guard
Validate before calling
// Resolve dirs through the driver itself
node, ok := dir.(*MegaNode)
if !ok {
resolved, err := d.Get(ctx, dir.GetPath())
if err != nil { return nil, err }
node, ok = resolved.(*MegaNode)
if !ok { return nil, fmt.Errorf("unresolvable dir type %T", dir) }
} Type guard
func isMegaNode(o model.Obj) bool {
_, ok := o.(*MegaNode)
return ok
} Try / catch
// Guard first; only call List with verified nodes
if !isMegaNode(dir) {
dir, err = d.Get(ctx, dir.GetPath())
if err != nil { return nil, err }
}
return d.List(ctx, dir, args) Prevention
- Never synthesize dir objects; use GetRoot()/List() results
- Route path-based access through driver.Get to re-materialize nodes
- Check the driver's own log line ('can't convert') for the offending type
When it happens
Trigger: Listing a directory object fabricated by another layer (path-based virtual object, mock, or cross-driver reference); passing model.Object value instead of *MegaNode; objects reconstructed after serialization between listing and listing a subfolder.
Common situations: File-manager frameworks that build virtual directory trees from paths; tests with generic fake objects; state restored from persistence losing the concrete node type.
Related errors
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/422fd8ca9c5d43c6.
Report an issue: GitHub.