{"record":{"id":"017835f100d73615","repo":"influxdata/influxdb","slug":"name-is-generic-only-may-take-type-parameters-in-a-catalog","errorCode":null,"errorMessage":"`{name}` is generic. Only {} may take type parameters in a catalog record, and any other generic must be parameterised solely by const literals (e.g. `Reserved<16>`); a generic body has no single persisted shape.","messagePattern":"`(.+?)` is generic\\. Only (.+?) may take type parameters in a catalog record, and any other generic must be parameterised solely by const literals \\(e\\.g\\. `Reserved<16>`\\); a generic body has no single persisted shape\\.","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"influxdb3_catalog_macros/src/types.rs","lineNumber":66,"sourceCode":"\n    match &segment.arguments {\n        PathArguments::None => Ok(()),\n        // Every argument a const literal, e.g. `Reserved<16>`. Permitted where\n        // a type parameter is not: the objection to a generic body is that it\n        // has no single persisted shape, and a const argument does have one.\n        // Each instantiation is also a distinct token sequence, so the shape\n        // fingerprint tells `Reserved<16>` from `Reserved<32>` and a change of\n        // width cannot slip through as compatible.\n        //\n        // Literals only. A named constant would fingerprint by name, so two\n        // names for one width would disagree and renaming a constant would\n        // move the shape without moving a byte.\n        PathArguments::AngleBracketed(args) if !args.args.is_empty() => {\n            if args.args.iter().all(is_const_literal) {\n                return Ok(());\n            }\n            if !CONTAINERS.contains(&name.as_str()) {\n                return Err(syn::Error::new(\n                    ty.span(),\n                    format!(\n                        \"`{name}` is generic. Only {} may take type parameters in a catalog \\\n                         record, and any other generic must be parameterised solely by const \\\n                         literals (e.g. `Reserved<16>`); a generic body has no single persisted \\\n                         shape.\",\n                        CONTAINERS.join(\" and \")\n                    ),\n                ));\n            }\n            let inner: Vec<&Type> = args\n                .args\n                .iter()\n                .filter_map(|arg| match arg {\n                    GenericArgument::Type(t) => Some(t),\n                    _ => None,\n                })\n                .collect();","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_catalog_macros/src/types.rs#L48-L84","documentation":"A compile-time error from the catalog record field-type checker. A field type may carry generic parameters only if it is one of the whitelisted CONTAINERS (e.g. `Option`, `Vec`) or if every parameter is a const literal (like `Reserved<16>`); anything else is rejected because a generic body has no single persisted shape the fingerprint can describe.","triggerScenarios":"Declaring a catalog record field like `field: MyWrapper<u64>` or `field: HashMap<String, u64>` where the name is not in `CONTAINERS` and the arguments are type (not const) parameters. Raised in `check_path` when const-literal check fails and the container check fails.","commonSituations":"A developer tries to store a map or a custom generic collection directly in a record, or parameterizes a helper type over a runtime type.","solutions":["Replace the generic type with a whitelisted container (`Option`, `Vec`) over allowed primitives, or a const-literal-parameterized type like `Reserved<16>`.","Define a concrete (non-generic) wire type in `records::types` for the data and convert to the runtime type in `apply`."],"exampleFix":"// before\n#[catalog_record(shape = 0x1)]\nstruct Foo { tags: HashMap<String, u64> }\n\n// after\n#[catalog_record(shape = 0x1)]\nstruct Foo { tags: Vec<(String, u64)> }","handlingStrategy":"validation","validationCode":"// Only allow generics on whitelisted containers or const literals:\n// OK: Option<u64>, Vec<String>, Reserved<16>\n// NOT OK: MyWrapper<u64>, HashMap<String, u64>","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Restrict record fields to Option/Vec containers or const-literal generics like Reserved<16>.","Do not put maps or custom generic collections directly in records.","Model complex data as concrete wire types in records::types."],"tags":["proc-macro","compile-time","generics","serialization"],"backgroundTag":"invalid-argument-value","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}