projectlombok/lombok · error · AnnotationValueDecodeFail

I can't make sense of this annotation value. Try using a…

Error message

I can't make sense of this annotation value. Try using a fully qualified literal.

What it means

AnnotationValues.getAsStringList() decodes annotation string-array members from the compiler's parse tree. When a value guess cannot be resolved to a String by guessToType() and there are multiple guesses (so no single-value default fallback applies), lombok throws AnnotationValueDecodeFail asking the user to write a fully qualified literal. This is lombok's way of rejecting annotation values it cannot statically interpret.

Solutions

  1. Replace the annotation value element with a plain string literal or fully qualified literal (e.g. fully spell out package.Class instead of an import-dependent select).
  2. Remove references to static fields/constants from the annotation value; Java annotations require compile-time constant literals.
  3. If a default exists for the method, use the single-value form so lombok can fall back to the default instead of throwing.
  4. Check for typos in the class/field name so guessToType can resolve it.
  5. Rebuild cleanly; stale incremental compilation state can leave guesses unresolved.

Example fix

// before
@Getter(value = {MyConstants.FOO, MyConstants.BAR})
// after
@Getter(value = {"foo", "bar"})
Defensive patterns

Strategy: validation

Validate before calling

function isPlainStringList(vals) { return Array.isArray(vals) && vals.every(v => typeof v === 'string' && !/[A-Za-z_$][\w$]*\s*\.[\w$]+/.test(v)); }
if (!isPlainStringList(myAnnotationValues)) throw new Error('Use plain string literals in the annotation');

Type guard

function isStringLiteral(v) { return typeof v === 'string'; }

Try / catch

try { List<String> l = annotationValues.getAsStringList("value"); } catch (AnnotationValueDecodeFail e) { log.error("Bad annotation value at index " + e.idx + ": use a fully qualified literal"); }

Prevention

When it happens

Trigger: A lombok annotation method expecting a String list receives an element that guessToType() cannot coerce to String (e.g. a FieldSelect referencing a field or an unresolvable select), and valueGuesses.size() > 1 so the getDefaultIf fallback path is skipped.

Common situations: Writing an annotation like @Getter(onMethod_=...) or a config annotation whose string array elements use non-literal references (e.g. SomeClass.CONSTANT) or typos in class references that fail qualification; also occurs after IDE refactors rename constants referenced from annotations.

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 projectlombok/lombok@6d6a3e9fec (2026-09-07). Data as JSON: /api/errors/c2361bfd1468d6cb. Report an issue: GitHub.

Appendix: source

Thrown at src/core/lombok/core/AnnotationValues.java:181

	
	public List<String> getAsStringList(String methodName) {
		AnnotationValue v = values.get(methodName);
		
		if (v == null) {
			String[] s = getDefaultIf(methodName, new String[0]);
			return Collections.unmodifiableList(Arrays.asList(s));
		}
		
		List<String> out = new ArrayList<String>(v.valueGuesses.size());
		int idx = 0;
		for (Object guess : v.valueGuesses) {
			Object result = guess == null ? null : guessToType(guess, String.class, v, idx);
			if (result == null) {
				if (v.valueGuesses.size() == 1) {
					String[] s = getDefaultIf(methodName, new String[0]);
					return Collections.unmodifiableList(Arrays.asList(s));
				} 
				throw new AnnotationValueDecodeFail(v, 
					"I can't make sense of this annotation value. Try using a fully qualified literal.", idx);
			}
			out.add((String) result);
			idx++;
		}
		
		return Collections.unmodifiableList(out);
	}
	
	public String getAsString(String methodName) {
		AnnotationValue v = values.get(methodName);
		if (v == null || v.valueGuesses.size() != 1) {
			return getDefaultIf(methodName, "");
		}
		
		Object guess = guessToType(v.valueGuesses.get(0), String.class, v, 0);
		if (guess instanceof String) return (String) guess;
		return getDefaultIf(methodName, "");

View on GitHub (pinned to 6d6a3e9fec)