{"record":{"id":"8f235d1a60ff7861","repo":"Hmbown/CodeWhale","slug":"legacy-import-refused-symlink-or-size-bound","errorCode":null,"errorMessage":"legacy import refused: symlink or size bound","messagePattern":"legacy import refused: symlink or size bound","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/native_memory.rs","lineNumber":506,"sourceCode":"        };\n        let access = Access::operator(scopes)?;\n        let store = self.open_structured()?;\n        // Entry surfaces show only live memory; candidates and reviewed-off\n        // entries are visible in the Context Lens, not here.\n        store\n            .list(&access, None, limit)?\n            .iter()\n            .filter(|m| matches!(m.status, Status::Active | Status::Stale))\n            .map(|m| self.hit(&store, &access, m, &Snapshot::default()))\n            .collect()\n    }\n    pub fn import_legacy(&self, path: &Path) -> Result<bool> {\n        if !path.is_file() {\n            return Ok(false);\n        }\n        let meta = fs::symlink_metadata(path)?;\n        if meta.file_type().is_symlink() || meta.len() > 1024 * 1024 {\n            bail!(\"legacy import refused: symlink or size bound\");\n        }\n        let text = fs::read_to_string(path)?;\n        let scope = Self::owner_scope();\n        let access = Access::operator(vec![scope.clone()])?;\n        let mut store = self.open_structured()?;\n        let report = codewhale_memory::import::markdown(\n            &mut store,\n            &access,\n            &scope,\n            \"codewhale:legacy-memory\",\n            &text,\n        )?;\n        if !report.rejected.is_empty() {\n            bail!(\n                \"legacy import left {} rejected notes unchanged; inspect before retry\",\n                report.rejected.len()\n            );\n        }","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/native_memory.rs#L488-L524","documentation":"native_memory import_legacy() imports a legacy markdown memory file only if it is a regular file of at most 1 MiB. Symlinks and oversized files are refused with this error — a security/robustness guard against symlink tricks (importing arbitrary files) and memory blowups from huge inputs.","triggerScenarios":"Calling import_legacy on a path that is a symlink (symlink_metadata reports a symlink file type) or a regular file larger than 1024*1024 bytes.","commonSituations":"Legacy MEMORY.md symlinked into a dotfiles repo; a legacy notes file that grew past 1 MiB over years of use; pointing import at a directory-like symlink or a synced/virtual file reported as oversized.","solutions":["Replace the symlink with a real copy of the target file inside the workspace.","Split or trim the legacy file to under 1 MiB before importing.","Import only the relevant portion of an oversized legacy file.","Verify the path with `ls -l` (or fs::symlink_metadata) to confirm it is a plain file under the size bound."],"exampleFix":"// before: symlinked legacy file\nln -s ~/dotfiles/MEMORY.md ~/.codewhale/MEMORY.md\n\n// after: real file copy under 1 MiB\ncp ~/dotfiles/MEMORY.md ~/.codewhale/MEMORY.md && truncate -s 900K ~/.codewhale/MEMORY.md","handlingStrategy":"validation","validationCode":"let meta = fs::symlink_metadata(path)?;\nif meta.file_type().is_symlink() || meta.len() > 1024 * 1024 {\n    return Err(\"legacy import requires a plain file under 1 MiB\".into());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store legacy memory files as real files, not symlinks into dotfile repos.","Rotate/trim legacy markdown memory before it grows past 1 MiB.","Check `ls -l` for symlink and size before pointing import_legacy at a path.","Migrate to structured storage instead of repeatedly re-importing legacy files."],"tags":["memory","import","symlink","file-size","security"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}