FuelLabs/fuels-rs · error · std::io::Error
failed to read storage slots from: {storage_path:?}: {e}
Error message
failed to read storage slots from: {storage_path:?}: {e} What it means
Runtime IO error from StorageSlots::load_from_file in fuels-programs: the storage-slots JSON passed existence and .json-extension checks but std::fs::read_to_string failed. The io::ErrorKind is preserved and the path plus underlying cause are embedded. This loader also runs implicitly via StorageConfiguration autoloading, which looks for <binary_stem>-storage_slots.json next to the contract binary.
Source
Thrown at packages/fuels-programs/src/contract/storage.rs:101
storage_slots: pairs.collect(),
}
}
pub(crate) fn add_overrides(
&mut self,
storage_slots: impl IntoIterator<Item = StorageSlot>,
) -> &mut Self {
let pairs = storage_slots.into_iter().map(|slot| (*slot.key(), slot));
self.storage_slots.extend(pairs);
self
}
pub(crate) fn load_from_file(storage_path: impl AsRef<Path>) -> Result<Self> {
let storage_path = storage_path.as_ref();
validate_path_and_extension(storage_path, "json")?;
let storage_json_string = std::fs::read_to_string(storage_path).map_err(|e| {
io::Error::new(
e.kind(),
format!("failed to read storage slots from: {storage_path:?}: {e}"),
)
})?;
let decoded_slots = serde_json::from_str::<Vec<StorageSlot>>(&storage_json_string)?;
Ok(StorageSlots::from(decoded_slots))
}
pub(crate) fn into_iter(self) -> impl Iterator<Item = StorageSlot> {
self.storage_slots.into_values()
}
}
pub(crate) fn determine_storage_slots(
storage_config: StorageConfiguration,
binary_filepath: &Path,View on GitHub (pinned to d9a250a518)
Solutions
- Read the embedded {e} cause and fix at OS level: chmod/copy with correct ownership for 'Permission denied'; re-run forc build if the file was being written concurrently.
- If the JSON is intentionally not wanted and autoloading keeps hitting it, disable autoloading via StorageConfiguration (set autoload to false) so the sibling file is ignored.
- Validate the JSON parses after access is fixed — the next failure mode is serde_json::Error on malformed content.
- Point storage to an explicit, known-good file path in LoadConfiguration/StorageConfiguration instead of relying on the sibling-file convention.
Example fix
// before: autoloading picks up an unreadable sibling JSON and fails let config = LoadConfiguration::default(); // after: disable autoloading so the sibling file is ignored let config = LoadConfiguration::new().with_storage_configuration(StorageConfiguration::default().with_autoload(false));
Defensive patterns
Strategy: try-catch
Validate before calling
let storage_path = std::path::Path::new(&storage_file);
if storage_path.exists() {
std::fs::read_to_string(storage_path)
.with_context(|| format!("storage slots file exists but is unreadable: {}", storage_path.display()))?;
serde_json::from_str::<Vec<StorageSlot>>(&std::fs::read_to_string(storage_path)?)
.with_context(|| "invalid storage slots JSON")?;
}
// or preempt autoloading entirely if the sibling JSON is not wanted
let cfg = StorageConfiguration::default().with_autoload(false); Try / catch
match StorageSlots::load_from_file(&path) {
Err(e) if e.to_string().contains("failed to read storage slots") => {
// Permission/transient FS issue: report the path and io cause, fix and retry once
eprintln!("unreadable storage file at {}: {e}", path.display());
return fix_permissions_and_retry(&path);
}
other => other,
} Prevention
- If you don't use storage-slot autoloading, disable it via StorageConfiguration with_autoload(false) so sibling JSON files are ignored.
- Ensure forc-generated *-storage_slots.json files keep readable permissions in CI.
- Validate the JSON parses (serde) after fixing access — read errors are only the first failure mode.
When it happens
Trigger: Explicitly configuring storage slots from a file whose permissions deny reading; or with autoloading enabled (the default), the sibling file <contract>-storage_slots.json exists but is unreadable (locked by another process, permissions, transient FS error) — note autoloading only engages when the file exists, so a plain missing file does not raise this.
Common situations: forc generates the storage-slots JSON alongside the binary but a CI step strips read permissions; Windows/macOS file locks while another build task still writes the JSON; a corrupted checkout or interrupted file sync; loading slots in a test harness that runs as a different user than the build step.
Related errors
- failed to read binary: {binary_filepath:?}: {e}
- must have exactly one element
- expected name='value'
- missing attribute '{name}'
- Unrecognized command. Expected one of: {msg}
AI-assisted analysis of FuelLabs/fuels-rs@d9a250a518 (2026-08-16).
Data as JSON: /api/errors/8abc17b2ccffb5aa.
Report an issue: GitHub.