cloudreve/cloudreve · warning
failed to read info of %q: %s, skipping...
Error message
failed to read info of %q: %s, skipping...
What it means
Produced by the Eject walk when fs.WalkDir hands its callback an error for an entry while exporting embedded static resources to disk (application/statics/statics.go:177-180). It formats the cause with %s, so errors.Is/errors.As cannot see through it. Although the message says 'skipping...', the code returns the error, which stops the entire walk and fails Eject - the skip is not actually performed.
Source
Thrown at application/statics/statics.go:179
})
var embedFS FS
embedFS.files = &files
return embedFS
}
// Eject 抽离内置静态资源
func Eject(l logging.Logger, statics fs.FS) error {
// 初始化静态资源
embedFS, err := fs.Sub(statics, "assets/build")
if err != nil {
l.Panic("Failed to initialize static resources: %s", err)
}
var walk func(relPath string, d fs.DirEntry, err error) error
walk = func(relPath string, d fs.DirEntry, err error) error {
if err != nil {
return fmt.Errorf("failed to read info of %q: %s, skipping...", relPath, err)
}
if !d.IsDir() {
// 写入文件
dst := util.DataPath(filepath.Join(StaticFolder, relPath))
out, err := util.CreatNestedFile(dst)
defer out.Close()
if err != nil {
return fmt.Errorf("failed to create file %q: %s, skipping...", dst, err)
}
l.Info("Ejecting %q...", dst)
obj, _ := embedFS.Open(relPath)
if _, err := io.Copy(out, bufio.NewReader(obj)); err != nil {
return fmt.Errorf("cannot write file %q: %s, skipping...", relPath, err)
}
}View on GitHub (pinned to 20c95ad73f)
Solutions
- Treat it as a broken embedded archive: rebuild the binary with a freshly built assets.zip.
- Validate the embedded archive independently (unzip -t on the source zip used at build time).
- If you want per-file resilience, change the handler to log and return nil so the walk really skips the entry, matching the message.
- Note the %s formatting: to inspect the cause programmatically, change it to %w first.
Example fix
// before
if err != nil {
return fmt.Errorf("failed to read info of %q: %s, skipping...", relPath, err)
}
// after - honor the "skipping" intent and keep the error chain
if err != nil {
l.Warning("failed to read info of %q, skipping: %s", relPath, err)
return nil
} Defensive patterns
Strategy: try-catch
Try / catch
// The message says "skipping..." but the shipped code returns the error,
// aborting the whole eject. Honor the intent:
if err != nil {
l.Warning("failed to read info of %q, skipping: %s", relPath, err)
return nil // continue walking siblings
}
// Note: shipped code uses %s, so errors.Is/As cannot see the cause. Prevention
- Rebuild the binary when embedded-archive walk errors appear; the source is inside the binary.
- Use %w (not %s) in wrapped errors so callers can classify causes.
- Decide skip-vs-abort explicitly: returning the error from a WalkDir callback stops the entire tree walk.
When it happens
Trigger: Reading a directory entry from the in-memory FS fails (corrupt embedded zip, same class as errors 115-117); d.Info() failing for an entry; memory pressure while enumerating a large archive. Because the FS is the already-materialized in-memory one, occurrences indicate a broken embedded archive rather than disk trouble.
Common situations: Running the eject command on a binary whose assets.zip is subtly corrupt; forks with modified asset pipelines producing odd entries.
Related errors
- cannot walk into %q: %w
- failed to create file %q: %s, skipping...
- failed to initialize static resources: %w
- canot open %q: %w
- cannot read %q: %w
AI-assisted analysis of cloudreve/cloudreve@20c95ad73f (2026-08-16).
Data as JSON: /api/errors/8d871f3035b90f9b.
Report an issue: GitHub.