influxdata/influxdb · error · syn::Error

` ` is a qualified path. A catalog record may only hold…

Error message

`{}` is a qualified path. A catalog record may only hold types whose encoding the catalog owns — declare a wire type in `records::types` and convert to the runtime type in `apply`.

What it means

A compile-time error from the catalog record field-type checker (`types::check_path`). Catalog records may only contain types whose wire encoding the catalog itself owns — bare single-segment path names. Qualified paths (`std::string::String`, `crate::Foo`) are rejected because the macro keys its type checks and fingerprint on simple type names and cannot own foreign/qualified encodings.

Solutions

  1. Import the type and use its bare name (`String` instead of `std::string::String`).
  2. For foreign types, declare a dedicated wire type in `records::types` and convert to the runtime type in the record's `apply` method.

Example fix

// before
#[catalog_record(shape = 0x1)]
struct Foo { s: std::string::String }

// after
#[catalog_record(shape = 0x1)]
struct Foo { s: String }
Defensive patterns

Strategy: validation

Validate before calling

// Use bare single-segment type names in record fields:
use std::string::String;
struct Foo { s: String } // OK, not std::string::String

Prevention

When it happens

Trigger: Declaring a catalog record field whose type is written as a qualified path with a leading `::` or more than one path segment, e.g. `field: std::collections::HashMap<u64, u64>`. Raised via `check` -> `check_path` during macro expansion.

Common situations: A developer writes the fully-qualified type out of habit or because of an import collision, or uses a type from another crate directly in the record.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/7c2e1380e0f34462. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_catalog_macros/src/types.rs:35

    "u128", "usize",
];

/// Containers that may wrap another allowed type.
const CONTAINERS: &[&str] = &["Option", "Vec"];

/// Check one field type against the allowlist.
pub(crate) fn check(ty: &Type) -> syn::Result<()> {
    match ty {
        Type::Array(array) => check(&array.elem),
        Type::Tuple(tuple) => tuple.elems.iter().try_for_each(check),
        Type::Path(path) if path.qself.is_none() => check_path(ty, &path.path),
        _ => Err(unsupported(ty)),
    }
}

fn check_path(ty: &Type, path: &syn::Path) -> syn::Result<()> {
    if path.leading_colon.is_some() || path.segments.len() > 1 {
        return Err(syn::Error::new(
            ty.span(),
            format!(
                "`{}` is a qualified path. A catalog record may only hold types whose encoding \
                 the catalog owns — declare a wire type in `records::types` and convert to the \
                 runtime type in `apply`.",
                render(ty)
            ),
        ));
    }

    let segment = &path.segments[0];
    let name = segment.ident.to_string();

    match &segment.arguments {
        PathArguments::None => Ok(()),
        // Every argument a const literal, e.g. `Reserved<16>`. Permitted where
        // a type parameter is not: the objection to a generic body is that it
        // has no single persisted shape, and a const argument does have one.

View on GitHub (pinned to 06200ef96b)