prestodb/presto · error · IllegalArgumentException

VARCHAR length must be a number

Error message

VARCHAR length must be a number

What it means

The single VARCHAR type parameter must be an integer long literal, not a type parameter, wildcard, or named parameter. This is thrown when VARCHAR is given one parameter that is not a numeric length, e.g. VARCHAR(x) where x is a generic type parameter or VARCHAR(varchar(5)).

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/type/VarcharParametricType.java:50

    public String getName()
    {
        return StandardTypes.VARCHAR;
    }

    @Override
    public Type createType(List<TypeParameter> parameters)
    {
        if (parameters.isEmpty()) {
            return createUnboundedVarcharType();
        }
        if (parameters.size() != 1) {
            throw new IllegalArgumentException("Expected exactly one parameter for VARCHAR");
        }

        TypeParameter parameter = parameters.get(0);

        if (!parameter.isLongLiteral()) {
            throw new IllegalArgumentException("VARCHAR length must be a number");
        }

        long length = parameter.getLongLiteral();

        if (length == VarcharType.UNBOUNDED_LENGTH) {
            return VarcharType.createUnboundedVarcharType();
        }

        if (length < 0 || length > VarcharType.MAX_LENGTH) {
            throw new IllegalArgumentException("Invalid VARCHAR length " + length);
        }

        return VarcharType.createVarcharType((int) length);
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use a concrete integer length: VARCHAR(50).
  2. If writing generic functions, declare the length parameter separately via @LiteralParameters('x') and use varchar(x) in the @SqlType annotation instead of a non-long TypeParameter.
  3. Fix the connector metadata to emit long literals for VARCHAR lengths.

Example fix

// before
@SqlType("varchar(T)")
// after
@LiteralParameters("x")
@SqlType("varchar(x)")
Defensive patterns

Strategy: validation

Validate before calling

boolean isValidVarcharParam(TypeParameter p) {
    return p == null || p.isLongLiteral();
}

Try / catch

try {
    Type t = typeManager.getParameterizedType("varchar", params);
} catch (IllegalArgumentException e) {
    // handle non-long-literal parameter: substitute a concrete length
}

Prevention

When it happens

Trigger: Type signatures like VARCHAR(T) in a templated function declaration, VARCHAR(json) style misuse, or a connector that supplies a TypeParameter which is not a LongLiteral to createType.

Common situations: Writing parametric-type-aware custom functions with type variable placeholders copied incorrectly, plugin metadata generation bugs.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/75fa83b1c37b4fe2. Report an issue: GitHub.