{"record":{"id":"caf081aea5339f53","repo":"jdx/mise","slug":"dotfile-enrollment-metadata-is-too-large","errorCode":null,"errorMessage":"dotfile enrollment metadata is too large","messagePattern":"dotfile enrollment metadata is too large","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/manifest.rs","lineNumber":412,"sourceCode":"        let Some((mode, oid)) = repo.object_at(tree, PATH)? else {\n            return Ok(None);\n        };\n        if mode != \"100644\" {\n            bail!(\"dotfile enrollment metadata must be a regular file\");\n        }\n        let bytes = repo.cat_object_bounded(&oid, 4 * 1024 * 1024)?;\n        Self::from_bytes(&bytes).map(Some)\n    }\n\n    pub(crate) fn read_gix(tree: &gix::Tree<'_>) -> Result<Option<Self>> {\n        let Some(entry) = tree.lookup_entry_by_path(PATH)? else {\n            return Ok(None);\n        };\n        if entry.mode().value() != 0o100644 {\n            bail!(\"dotfile enrollment metadata must be a regular file\");\n        }\n        if entry.id().header()?.size() > 4 * 1024 * 1024 {\n            bail!(\"dotfile enrollment metadata is too large\");\n        }\n        let object = entry.object()?;\n        Self::from_bytes(&object.data).map(Some)\n    }\n\n    fn from_bytes(bytes: &[u8]) -> Result<Self> {\n        #[derive(Deserialize)]\n        struct FormatHeader {\n            format: u64,\n        }\n        let header: FormatHeader = serde_json::from_slice(bytes)?;\n        if header.format != 1 {\n            bail!(\"unsupported dotfile repository format {}\", header.format);\n        }\n        let manifest: Self = serde_json::from_slice(bytes)?;\n        manifest.validate()?;\n        Ok(manifest)\n    }","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/manifest.rs#L394-L430","documentation":"The dotfile enrollment manifest blob is size-checked while reading it from git; any manifest larger than 4 MiB is rejected. This is a defensive cap so a corrupted or malicious history repository cannot force the parser to load arbitrarily large objects into memory.","triggerScenarios":"read_gix finds the manifest entry in mode 0100644 but `entry.id().header()?.size()` exceeds 4 * 1024 * 1024 bytes — e.g. the blob was overwritten with binary data, a log, or an accidentally committed large file at the manifest path.","commonSituations":"A crash or bad script concatenated repeated JSON into the manifest; someone committed a snapshot/dump file over the manifest path; a sync tool rewrote the manifest with embedded base64 blobs.","solutions":["Restore a manifest under 4 MiB from git history: `git checkout <ref> -- <path>`.","Inspect the blob (`git cat-file -p <blob-id> | wc -c`) to see what inflated it; if it is duplicated JSON, rebuild the manifest by re-enrolling dotfiles.","Remove foreign content accidentally committed at the manifest path and re-commit the real manifest.","If the store is unrecoverable, delete/reinit the dotfile history store and let mise recreate a fresh manifest."],"exampleFix":"// before: inspect oversized blob\ngit cat-file -p $(git rev-parse HEAD:path/to/manifest) | wc -c  # 9 MB\n// after: restore a good version\ngit log --oneline -- path/to/manifest\ngit checkout <good-commit> -- path/to/manifest\ngit commit -m 'restore valid manifest'","handlingStrategy":"validation","validationCode":"const MAX_MANIFEST_BYTES = 4 * 1024 * 1024;\nexport function assertManifestSize(bytes: Uint8Array): void {\n  if (bytes.byteLength > MAX_MANIFEST_BYTES) {\n    throw new Error(`manifest is ${bytes.byteLength} bytes; max is 4 MiB`);\n  }\n}","typeGuard":"function isWithinManifestLimit(size: number): boolean {\n  return size <= 4 * 1024 * 1024;\n}","tryCatchPattern":null,"preventionTips":["Keep the manifest minimal; do not embed file contents in it","Verify manifest size before committing: `wc -c manifest.json`","Watch for crash loops appending duplicate entries to the manifest"],"tags":["git","manifest","size-limit","dotfiles"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}