github/copilot-sdk · error · IllegalArgumentException

must be 'true' or 'false'

Error message

must be 'true' or 'false'

What it means

When a Param's declared type is Boolean/boolean, validateDefaultValue checks that the defaultValue string is exactly 'true' or 'false' (case-insensitive); otherwise it throws this IllegalArgumentException. Note the message omits field context, but it is raised only for boolean-typed parameters during construction.

Solutions

  1. Change the defaultValue to "true" or "false".
  2. Normalize the incoming config value before constructing the Param (map yes/on/1 to true).
  3. Use Boolean.parseBoolean's accepted set as your validation upstream so only true/false reach Param.

Example fix

// before
new Param("verbose", "desc", Type.BOOLEAN, "yes", false, null);
// after
new Param("verbose", "desc", Type.BOOLEAN, "true", false, null);
Defensive patterns

Strategy: validation

Validate before calling

static String normalizeBooleanDefault(String v) {
    if (v == null) return null;
    String t = v.trim().toLowerCase();
    switch (t) {
        case "true": case "yes": case "on": case "1": return "true";
        case "false": case "no": case "off": case "0": return "false";
        default: throw new IllegalArgumentException("boolean default must be true/false: " + v);
    }
}

Type guard

static boolean isBooleanLiteral(String s) {
    return "true".equalsIgnoreCase(s) || "false".equalsIgnoreCase(s);
}

Try / catch

try {
    new Param(name, desc, Boolean.class, def, false, null);
} catch (IllegalArgumentException e) {
    if (e.getMessage().equals("must be 'true' or 'false'")) {
        // def was not a boolean literal — normalize and retry
    }
    throw e;
}

Prevention

When it happens

Trigger: new Param(..., type=Boolean.class, defaultValue="yes"/"1"/"on"/"true ") — any string other than true/false (ignoring case).

Common situations: Config files using truthy conventions like yes/no or 1/0, YAML-style booleans pasted into a JSON/Java context, trailing whitespace from untrimmed config values.

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 github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/e0cfc16f587fb871. Report an issue: GitHub.

Appendix: source

Thrown at java/sdk/src/main/java/com/github/copilot/tool/Param.java:278

            if (type == Double.class || type == double.class) {
                Double.parseDouble(defaultValue);
                return;
            }
            if (type == Float.class || type == float.class) {
                Float.parseFloat(defaultValue);
                return;
            }
            if (type == Short.class || type == short.class) {
                Short.parseShort(defaultValue);
                return;
            }
            if (type == Byte.class || type == byte.class) {
                Byte.parseByte(defaultValue);
                return;
            }
            if (type == Boolean.class || type == boolean.class) {
                if (!"true".equalsIgnoreCase(defaultValue) && !"false".equalsIgnoreCase(defaultValue)) {
                    throw new IllegalArgumentException("must be 'true' or 'false'");
                }
                return;
            }
            if (type.isEnum()) {
                Class<? extends Enum> enumType = (Class<? extends Enum>) type;
                Enum.valueOf(enumType, defaultValue);
                return;
            }
        } catch (RuntimeException ex) {
            throw new IllegalArgumentException(
                    "defaultValue '" + defaultValue + "' is not valid for type " + type.getSimpleName(), ex);
        }

        throw new IllegalArgumentException(
                "defaultValue is not supported for type " + type.getName() + " without a custom coercion policy");
    }
}

View on GitHub (pinned to cd8cf15dc3)