sinelaw/fresh · error
Failed to read
Error message
Failed to read {}: {} What it means
While recursively walking a plugin bundle's import graph, `collect_modules` tries to read each imported file from disk; any I/O failure (missing file, permission, invalid UTF-8 via read_to_string) is wrapped with the path and the underlying io::Error. Bundling cannot proceed without the module's contents.
Solutions
- Fix or create the file at the path shown in the message.
- Correct the import specifier in the importing module to match the actual file name/case.
- Vendor or remove imports of external packages (e.g. node_modules-only deps) not present in the bundle root.
- Re-save the file as UTF-8 if it contains invalid bytes.
Example fix
// before
import { helper } from "./heplper.ts"; // typo
// after
import { helper } from "./helper.ts"; Defensive patterns
Strategy: try-catch
Validate before calling
// Check entry and its import targets exist before bundling
let p = std::path::Path::new(entry);
if !p.is_file() { bail!("entry file missing: {}", entry); } Try / catch
match bundle_module(entry) {
Err(e) if e.to_string().starts_with("Failed to read ") => {
log::error!("bundle aborted, missing module: {e}");
disable_plugin(entry);
}
other => other?,
} Prevention
- Use relative, case-correct import paths and verify files exist after moves/renames.
- Vendor all third-party imports into the plugin directory.
- Save sources as UTF-8 and add a pre-bundle existence check for each import.
When it happens
Trigger: Calling `collect_modules` (directly or via bundle_module) on an entry file whose imports point to a path that doesn't exist, is a directory, lacks read permission, or contains non-UTF-8 bytes.
Common situations: Plugin imports a typo'd relative path; module file deleted or moved after the import was written; importing a node_modules package that isn't vendored on disk; file saved with a non-UTF-8 encoding.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- Cannot resolve import
- Failed to read plugin
- home directory not found
- Filesystem not available
- read_range: expected
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/e498deac6e6839c6.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-parser-js/src/lib.rs:366
Ok(output)
}
/// Collect all modules in dependency order (dependencies first)
fn collect_modules(
path: &Path,
visited: &mut HashSet<PathBuf>,
modules: &mut Vec<ModuleMetadata>,
path_to_var: &mut std::collections::HashMap<PathBuf, String>,
) -> Result<()> {
let canonical = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
if visited.contains(&canonical) {
return Ok(()); // Already processed (circular import protection)
}
visited.insert(canonical.clone());
let source = std::fs::read_to_string(path)
.map_err(|e| anyhow!("Failed to read {}: {}", path.display(), e))?;
// Extract module metadata using AST
let (imports, exports, reexports) = extract_module_bindings(&source);
let parent_dir = path.parent().unwrap_or(Path::new("."));
// Collect dependencies first (topological order)
for import in &imports {
if import.source_path.starts_with("./") || import.source_path.starts_with("../") {
let resolved = resolve_import(&import.source_path, parent_dir)?;
collect_modules(&resolved, visited, modules, path_to_var)?;
}
}
for reexport in &reexports {
if reexport.source_path.starts_with("./") || reexport.source_path.starts_with("../") {
let resolved = resolve_import(&reexport.source_path, parent_dir)?;
collect_modules(&resolved, visited, modules, path_to_var)?;
}View on GitHub (pinned to 67894ca546)