OtterMind/Chat2DB · error · IllegalArgumentException

Invalid DM BIT literal: {value}

Error message

Invalid DM BIT literal: {value}

What it means

Thrown by DMSqlGuards.requireBitLiteral when a DM BIT column default literal is not one of the accepted truthy/falsy forms. The guard accepts blank (returns "NULL"), "0"/"false" (returns "0"), and "1"/"true" (returns "1"); any other value is rejected so a non-escapable default cannot be embedded in DDL.

Source

Thrown at chat2db-community-server/chat2db-community-plugins/chat2db-community-dm/src/main/java/ai/chat2db/plugin/dm/DMSqlGuards.java:79

        }
        if ("DESC".equalsIgnoreCase(trimmed)) {
            return "DESC";
        }
        throw new IllegalArgumentException("Invalid DM index sort direction: " + value);
    }

    public static String requireBitLiteral(String value) {
        if (StringUtils.isBlank(value)) {
            return "NULL";
        }
        String trimmed = StringUtils.trimToEmpty(value);
        if ("0".equals(trimmed) || "false".equalsIgnoreCase(trimmed)) {
            return "0";
        }
        if ("1".equals(trimmed) || "true".equalsIgnoreCase(trimmed)) {
            return "1";
        }
        throw new IllegalArgumentException("Invalid DM BIT literal: " + value);
    }

    private static void scanExpression(String expression, boolean typeExpression, String description) {
        Deque<Character> delimiters = new ArrayDeque<>();
        List<String> topLevelWords = new ArrayList<>();
        boolean sawToken = false;

        for (int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);
            if (Character.isISOControl(c)) {
                throw invalid(description, expression);
            }
            if (Character.isWhitespace(c)) {
                continue;
            }
            sawToken = true;

            if (isAlternativeQuoteStart(expression, i)) {

View on GitHub (pinned to 5ee1e990e7)

Solutions

  1. Convert boolean-ish inputs to "0"/"1" before calling requireBitLiteral.
  2. Leave the default blank if the column should default to NULL.
  3. Normalize at the import layer: map on/yes/true->"1" and off/no/false->"0".

Example fix

// before
String d = column.getDefaultValue(); // "yes"
DDL.append(" DEFAULT ").append(DMSqlGuards.requireBitLiteral(d));

// after
String d = column.getDefaultValue();
if ("on".equalsIgnoreCase(d) || "yes".equalsIgnoreCase(d) || "true".equalsIgnoreCase(d)) d = "1";
else if ("off".equalsIgnoreCase(d) || "no".equalsIgnoreCase(d) || "false".equalsIgnoreCase(d)) d = "0";
DDL.append(" DEFAULT ").append(DMSqlGuards.requireBitLiteral(d));
Defensive patterns

Strategy: validation

Validate before calling

static boolean isDmBitLiteral(String v) {
    if (v == null || v.trim().isEmpty()) return true; // -> NULL
    String t = v.trim().toLowerCase(Locale.ROOT);
    return "0".equals(t) || "1".equals(t) || "true".equals(t) || "false".equals(t);
}

Type guard

static String dmBitOrSkip(String v) {
    if (v == null || v.trim().isEmpty()) return null; // skip DEFAULT
    String t = v.trim().toLowerCase(Locale.ROOT);
    if (Set.of("0","false").contains(t)) return "0";
    if (Set.of("1","true").contains(t)) return "1";
    return null; // unsupported -> skip
}

Prevention

When it happens

Trigger: Calling DMSqlGuards.requireBitLiteral(value) with a value like "2", "T", "yes", "b'1'", or an expression string. Reached when generating DDL for a DM BIT column whose default value is being normalized.

Common situations: Copying a BIT/TINYINT(1) default from MySQL-style schemas that use 0/1 with extra formatting; a UI submitting a boolean as "on"/"off" or "yes"; importing metadata whose default text includes quotes or casts.

Related errors


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