OtterMind/Chat2DB · error · IllegalArgumentException

Invalid generic {what}: {value}

Error message

Invalid generic {what}: {value}

What it means

Thrown by GenericSqlGuards.requireSafeIdentifier when a value fails the strict identifier allow-list ^[A-Za-z0-9_$]+$. The generic adapter cannot know each dialect's identifier quote character, so bare-identifier template positions are restricted to this safe character set rather than escaped. Null or any character outside [A-Za-z0-9_$] is rejected.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-generic/src/main/java/ai/chat2db/plugin/generic/GenericSqlGuards.java:30

 * The generic adapter serves mixed dialects via DBConfig templates (e.g. DuckDB wraps
 * placeholders in single quotes, TDengine uses bare identifier positions), so treatment
 * is chosen per placeholder by inspecting the template; no single dialect quote char is
 * hard-coded. Escaping itself lives in {@link GenericIdentifierProcessor}.
 */
public final class GenericSqlGuards {

    private static final Pattern SAFE_IDENTIFIER_PATTERN = Pattern.compile("^[A-Za-z0-9_$]+$");

    private GenericSqlGuards() {
    }

    /**
     * Validate a strict identifier token for bare-identifier template positions, where the
     * generic adapter cannot know the dialect's identifier quote char.
     */
    public static String requireSafeIdentifier(String value, String what) {
        if (value == null || !SAFE_IDENTIFIER_PATTERN.matcher(value).matches()) {
            throw new IllegalArgumentException("Invalid generic " + what + ": " + value);
        }
        return value;
    }

    /**
     * Sanitize a value that DBConfig substitutes for {@code placeholder} in the given
     * generic.json SQL template. A placeholder wrapped in single quotes ('{database}')
     * lands in string-literal position and gets literal escaping; a bare placeholder
     * ({database}) lands in identifier position and must pass the identifier whitelist.
     */
    public static String sanitizeTemplateValue(String template, String placeholder, String value) {
        if (template == null || StringUtils.isBlank(value)) {
            return value;
        }
        if (template.contains("'" + placeholder + "'")) {
            return GenericIdentifierProcessor.INSTANCE.escapeString(value);
        }
        return requireSafeIdentifier(value, placeholder);

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Use a simple identifier (letters, digits, underscore, dollar) for values that flow into bare-identifier generic templates.
  2. If the name needs special characters, use a dialect-specific path that quotes identifiers instead of the generic template.
  3. Validate names against SAFE_IDENTIFIER_PATTERN before submitting a generic SQL request.

Example fix

// before
String db = "my-db"; // hyphen not in safe set
GenericSqlGuards.requireSafeIdentifier(db, "database");

// after
String db = "my_db"; // only [A-Za-z0-9_$]
GenericSqlGuards.requireSafeIdentifier(db, "database");
Defensive patterns

Strategy: validation

Validate before calling

private static final java.util.regex.Pattern SAFE_ID = java.util.regex.Pattern.compile("^[A-Za-z0-9_$]+$");
static boolean isSafeGenericIdentifier(String v) {
    return v != null && SAFE_ID.matcher(v).matches();
}

Type guard

static String safeIdOrNull(String v) {
    return (v != null && SAFE_ID.matcher(v).matches()) ? v : null;
}

Prevention

When it happens

Trigger: Calling GenericSqlGuards.requireSafeIdentifier(value, what) with a null value or a value containing spaces, quotes, dots, unicode, or punctuation; or DBConfig substituting a value for a bare placeholder like {database} via sanitizeTemplateValue.

Common situations: A schema/database/table name containing a hyphen, space, or dot used in a generic SQL template that has no quoting; a non-ASCII identifier from a migrated schema; an empty or null identifier passed to a generic connection/list command.

Related errors


AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14). Data as JSON: /api/errors/9066e678c68dab5d. Report an issue: GitHub.