risingwavelabs/risingwave · critical

failed to lookup type matrix: unknown type

Error message

failed to lookup type matrix: unknown type: {}

What it means

`lookup_matrix` in src/expr/macro/src/types.rs resolves type names (int4, varchar, ...) against a fixed TYPE_MATRIX table to obtain data/array/owned/ref types. Any type string that does not match a row (after `[]`→anyarray, `struct*`→struct, `void`→int4 normalization) panics with "failed to lookup type matrix: unknown type: {}".

Solutions

  1. Use exact matrix names: int2/int4/int8, float4/float8, varchar, bytea, boolean, decimal, date, time, timestamp, timestamptz, interval, jsonb, etc.
  2. If the type genuinely doesn't exist, add a new row to TYPE_MATRIX in src/expr/macro/src/types.rs.
  3. Remember `[]`, `struct<...>`, and `void` are auto-normalized; other aliases are not — normalize your string yourself if needed.

Example fix

// before - `int` is not in the type matrix
#[function("my_add(int, int)")]

// after
#[function("my_add(int4, int4)")]
Defensive patterns

Strategy: validation

Validate before calling

const MATRIX_NAMES: &[&str] = &["boolean","int2","int4","int8","int256","float4","float8","decimal","serial","date","time","timestamp","timestamptz","interval","varchar","bytea","jsonb","variant","vector","anyarray","struct","anymap","any"];
fn type_known(ty: &str) -> bool {
    let t = if ty.ends_with("[]") { "anyarray" }
        else if ty.starts_with("struct") { "struct" }
        else if ty == "void" { "int4" } else { ty };
    MATRIX_NAMES.contains(&t)
}
assert!(type_known("int4"));
assert!(!type_known("int"));

Prevention

When it happens

Trigger: Declaring `#[function]` or `#[aggregate]` signatures using unsupported or misspelled type names such as `int`, `integer`, `text`, `string`, `float`, or a custom type not present in TYPE_MATRIX; this panic propagates through data_type/array_type/owned_type/ref_type/is_primitive.

Common situations: Developers writing SQL-ish names instead of the internal short names (int4 vs int, varchar vs text); using a newly introduced type before adding it to the matrix; case mismatches (`INT4`).

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/9a0affed837734f8. Report an issue: GitHub.

Appendix: source

Thrown at src/expr/macro/src/types.rs:87

fn lookup_matrix(mut ty: &str, idx: usize) -> &str {
    if ty.ends_with("[]") {
        ty = "anyarray";
    } else if ty.starts_with("struct") {
        ty = "struct";
    } else if ty == "void" {
        // XXX: we don't support void type yet.
        //      replace it with int for now.
        ty = "int4";
    }
    let s = TYPE_MATRIX.trim().lines().find_map(|line| {
        let mut parts = line.split_whitespace();
        if parts.next() == Some(ty) {
            Some(parts.nth(idx - 1).unwrap())
        } else {
            None
        }
    });
    s.unwrap_or_else(|| panic!("failed to lookup type matrix: unknown type: {}", ty))
}

/// Expands a type wildcard string into a list of concrete types.
pub fn expand_type_wildcard(ty: &str) -> Vec<&str> {
    match ty {
        "*" => TYPE_MATRIX
            .trim()
            .lines()
            .map(|l| l.split_whitespace().next().unwrap())
            .filter(|l| *l != "any")
            .collect(),
        "*int" => vec!["int2", "int4", "int8"],
        "*float" => vec!["float4", "float8"],
        _ => vec![ty],
    }
}

/// Computes the minimal compatible type between a pair of data types.

View on GitHub (pinned to 6469eb736d)