{"record":{"id":"8ea583e091747977","repo":"spacedriveapp/spacedrive","slug":"failed-to-parse-group-type","errorCode":null,"errorMessage":"Failed to parse group_type: {}","messagePattern":"Failed to parse group_type: (.+?)","errorType":"exception","errorClass":"CoreError","httpStatus":null,"severity":"error","filePath":"core/src/domain/space.rs","lineNumber":192,"sourceCode":"\n\t\tlet group_models = space_group::Entity::find()\n\t\t\t.filter(space_group::Column::Uuid.is_in(ids.to_vec()))\n\t\t\t.all(db)\n\t\t\t.await?;\n\n\t\tlet mut results = Vec::new();\n\n\t\tfor group_model in group_models {\n\t\t\t// Fetch parent space to get space_id (UUID)\n\t\t\tlet space_model = space::Entity::find_by_id(group_model.space_id)\n\t\t\t\t.one(db)\n\t\t\t\t.await?;\n\n\t\t\tlet space_id = space_model.map(|s| s.uuid).unwrap_or(group_model.uuid);\n\n\t\t\tlet group_type: GroupType =\n\t\t\t\tserde_json::from_str(&group_model.group_type).map_err(|e| {\n\t\t\t\t\tcrate::common::errors::CoreError::Other(anyhow::anyhow!(\n\t\t\t\t\t\t\"Failed to parse group_type: {}\",\n\t\t\t\t\t\te\n\t\t\t\t\t))\n\t\t\t\t})?;\n\n\t\t\tresults.push(SpaceGroup {\n\t\t\t\tid: group_model.uuid,\n\t\t\t\tspace_id,\n\t\t\t\tname: group_model.name,\n\t\t\t\tgroup_type,\n\t\t\t\tis_collapsed: group_model.is_collapsed,\n\t\t\t\torder: group_model.order,\n\t\t\t\tcreated_at: group_model.created_at.into(),\n\t\t\t});\n\t\t}\n\n\t\tOk(results)\n\t}","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/spacedriveapp/spacedrive/blob/6dfeccf2113039e35f2ce735f945e70dc3e4ea45/core/src/domain/space.rs#L174-L210","documentation":"SpaceGroup hydration (core/src/domain/space.rs:192) parses the space_group.group_type TEXT column with serde_json::from_str into GroupType. GroupType is a serde externally-tagged enum, so valid stored values are strings like \"QuickAccess\", \"Devices\", \"Locations\", \"Volumes\", \"Tags\", \"Sources\", \"Cloud\", \"Custom\" or objects like {\"Device\":{\"device_id\":\"<uuid>\"}}. Any other content (renamed variant, snake_case spelling, truncated JSON) makes from_str fail and the whole query returns CoreError::Other('Failed to parse group_type: ...').","triggerScenarios":"Loading spaces whose space_group rows were written by an older/newer build with different GroupType variants or casing; rows hand-edited in SQLite; a migration that wrote snake_case ('quick_access') instead of PascalCase; a variant renamed or removed between versions.","commonSituations":"Downgrading to an older app version against a newer library DB; running two daemon versions against the same ~/.spacedrive data dir; manual DB surgery; schema drift between desktop and a prototype client.","solutions":["Inspect the offending rows: `SELECT id, group_type FROM space_group;` and compare against the valid values above.","Repair the data in place with valid JSON, e.g. UPDATE space_group SET group_type='\"Custom\"' WHERE group_type='quick_access';","If a variant was renamed, keep old data loadable with #[serde(alias = \"OldName\")] on the enum variant instead of editing every row.","Never run a daemon older than the version that created the library."],"exampleFix":"# before: row contains invalid value\nsqlite> SELECT group_type FROM space_group WHERE id=7;\nquick_access\n\n# after\nsqlite> UPDATE space_group SET group_type='\"QuickAccess\"' WHERE id=7;","handlingStrategy":"try-catch","validationCode":"// write-side guard: only persist group_type values that round-trip\nfn valid_group_type_json(v: &str) -> bool {\n    matches!(\n        serde_json::from_str::<GroupType>(v),\n        Ok(_)\n    )\n}\nassert!(valid_group_type_json(&serde_json::to_string(&group_type)?));","typeGuard":"fn parse_group_type(s: &str) -> Option<GroupType> {\n    serde_json::from_str(s).ok()\n}","tryCatchPattern":"// per-row handling: quarantine the bad group, keep the rest of the space loadable\nfor m in group_models {\n    let group_type = match serde_json::from_str(&m.group_type) {\n        Ok(t) => t,\n        Err(e) => {\n            tracing::warn!(group_id = %m.uuid, error = %e, \"skipping unparseable group_type\");\n            continue;\n        }\n    };\n    // ...\n}","preventionTips":["Only write group_type via serde_json::to_string(&GroupType) — never hand-format strings.","Add #[serde(alias)] when renaming variants instead of leaving old rows stranded.","Do not share a library DB between different core versions."],"tags":["database","serde","spaces","data-corruption"],"backgroundTag":null,"analyzedSha":"6dfeccf2113039e35f2ce735f945e70dc3e4ea45","analyzedAt":"2026-08-16T11:26:17.074Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}