{"record":{"id":"8abc17b2ccffb5aa","repo":"FuelLabs/fuels-rs","slug":"failed-to-read-storage-slots-from-storage-path","errorCode":null,"errorMessage":"failed to read storage slots from: {storage_path:?}: {e}","messagePattern":"failed to read storage slots from: (.+?): (.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"packages/fuels-programs/src/contract/storage.rs","lineNumber":101,"sourceCode":"            storage_slots: pairs.collect(),\n        }\n    }\n\n    pub(crate) fn add_overrides(\n        &mut self,\n        storage_slots: impl IntoIterator<Item = StorageSlot>,\n    ) -> &mut Self {\n        let pairs = storage_slots.into_iter().map(|slot| (*slot.key(), slot));\n        self.storage_slots.extend(pairs);\n        self\n    }\n\n    pub(crate) fn load_from_file(storage_path: impl AsRef<Path>) -> Result<Self> {\n        let storage_path = storage_path.as_ref();\n        validate_path_and_extension(storage_path, \"json\")?;\n\n        let storage_json_string = std::fs::read_to_string(storage_path).map_err(|e| {\n            io::Error::new(\n                e.kind(),\n                format!(\"failed to read storage slots from: {storage_path:?}: {e}\"),\n            )\n        })?;\n\n        let decoded_slots = serde_json::from_str::<Vec<StorageSlot>>(&storage_json_string)?;\n\n        Ok(StorageSlots::from(decoded_slots))\n    }\n\n    pub(crate) fn into_iter(self) -> impl Iterator<Item = StorageSlot> {\n        self.storage_slots.into_values()\n    }\n}\n\npub(crate) fn determine_storage_slots(\n    storage_config: StorageConfiguration,\n    binary_filepath: &Path,","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/FuelLabs/fuels-rs/blob/d9a250a51818dda64bfeb5ef7cc19cf27bdcd623/packages/fuels-programs/src/contract/storage.rs#L83-L119","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: autoloading picks up an unreadable sibling JSON and fails\nlet config = LoadConfiguration::default();\n// after: disable autoloading so the sibling file is ignored\nlet config = LoadConfiguration::new().with_storage_configuration(StorageConfiguration::default().with_autoload(false));","handlingStrategy":"try-catch","validationCode":"let storage_path = std::path::Path::new(&storage_file);\nif storage_path.exists() {\n    std::fs::read_to_string(storage_path)\n        .with_context(|| format!(\"storage slots file exists but is unreadable: {}\", storage_path.display()))?;\n    serde_json::from_str::<Vec<StorageSlot>>(&std::fs::read_to_string(storage_path)?)\n        .with_context(|| \"invalid storage slots JSON\")?;\n}\n// or preempt autoloading entirely if the sibling JSON is not wanted\nlet cfg = StorageConfiguration::default().with_autoload(false);","typeGuard":null,"tryCatchPattern":"match StorageSlots::load_from_file(&path) {\n    Err(e) if e.to_string().contains(\"failed to read storage slots\") => {\n        // Permission/transient FS issue: report the path and io cause, fix and retry once\n        eprintln!(\"unreadable storage file at {}: {e}\", path.display());\n        return fix_permissions_and_retry(&path);\n    }\n    other => other,\n}","preventionTips":["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."],"tags":["rust","runtime","io","storage-slots","fuels-programs"],"backgroundTag":null,"analyzedSha":"d9a250a51818dda64bfeb5ef7cc19cf27bdcd623","analyzedAt":"2026-08-16T09:49:30.618Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}