java-decompiler/jd-gui · error · RuntimeException

SignatureWriter.WriteSignature: invalid signature '${descrip

Error message

SignatureWriter.WriteSignature: invalid signature '${descriptor}'

What it means

The signature writer in AbstractTypeFactoryProvider converts JVM type descriptors (e.g. 'Ljava/lang/String;') into readable Java types. When it encounters a character at the start of a type that is not a recognized descriptor or wildcard/signature marker (invalid 'BaseType' character), it throws a RuntimeException naming the whole descriptor. This guards against corrupted class files or descriptors that were truncated or parsed at a wrong index.

Source

Thrown at services/src/main/java/org/jd/gui/service/type/AbstractTypeFactoryProvider.java:168

                    beginIndex = ++index;
                    index = descriptor.substring(beginIndex, length).indexOf(';');
                    sb.append(descriptor.substring(beginIndex, index));
                    index++;
                    break;
                case 'V': sb.append("void"); index++; break;
                case 'Z': sb.append("boolean"); index++; break;
                case '-':
                    sb.append("? super ");
                    index = writeSignature(sb, descriptor, length, index+1, false);
                    break;
                case '+':
                    sb.append("? extends ");
                    index = writeSignature(sb, descriptor, length, index+1, false);
                    break;
                case '*': sb.append('?'); index++; break;
                case 'X': case 'Y': sb.append("int"); index++; break;
                default:
                    throw new RuntimeException("SignatureWriter.WriteSignature: invalid signature '" + descriptor + "'");
            }

            if (varargsFlag) {
                if (dimensionLength > 0) {
                    while (--dimensionLength > 0)
                        sb.append("[]");
                    sb.append("...");
                }
            } else {
                while (dimensionLength-- > 0)
                    sb.append("[]");
            }

            if ((index >= length) || (descriptor.charAt(index) != '.'))
                break;

            sb.append('.');
        }

View on GitHub (pinned to b3c1ced04e)

Solutions

  1. Verify the class file is valid: recompile or re-obtain the artifact from a trusted source (javap -v can confirm the Signature/descriptor attributes).
  2. Check that the descriptor string passed to the type factory is a full type descriptor and not truncated or offset — a wrong starting index lands mid-identifier and hits the default branch.
  3. Upgrade JD-GUI to the latest release; support for signature encodings has been extended over time.
  4. If you maintain the code, log the failing index and character before throwing to pinpoint which construct is unsupported.

Example fix

// before
default:
    throw new RuntimeException("SignatureWriter.WriteSignature: invalid signature '" + descriptor + "'");
// after
default:
    if (Character.isJavaIdentifierStart(c)) { // fallback: treat as class name char
        sb.append(c); index++; break;
    }
    throw new RuntimeException("SignatureWriter.WriteSignature: invalid signature '" + descriptor + "' at index " + index + " char '" + c + "'");
Defensive patterns

Strategy: validation

Validate before calling

// Check the descriptor starts with a legal BaseType/ObjectType/ArrayType char
boolean isLikelyValidTypeDescriptor(String d) {
    if (d == null || d.isEmpty()) return false;
    char c = d.charAt(0);
    return "BCDFIJSVZ".indexOf(c) >= 0 || c == 'L' || c == '[' || c == 'T' || c == '+' || c == '-' || c == '*';
}

Type guard

boolean isObjectTypeDescriptor(String d) {
    return d != null && d.startsWith("L") && d.endsWith(";");
}

Try / catch

try {
    String readable = typeFactory.make(api, entry, descriptor).getDisplayTypeName();
} catch (RuntimeException ex) {
    if (ex.getMessage() != null && ex.getMessage().startsWith("SignatureWriter.WriteSignature:")) {
        // fall back to showing the raw descriptor
        readable = descriptor;
    } else throw ex;
}

Prevention

When it happens

Trigger: writeSignature (or writeMethodSignature via it) processing a descriptor whose current character is not one of B/C/D/F/I/J/S/V/Z/L/T/[/*+/-/X/Y — typically a truncated descriptor, an index pointing mid-identifier, or a class file with corrupted constant-pool/Signature attributes.

Common situations: Opening a class file compiled by a non-standard or buggy compiler; obfuscated or deliberately malformed bytecode; a JD-GUI version not supporting newer signature constructs (e.g. some compilations with X/Y handling); passing a method descriptor instead of a field/type descriptor into the type factory.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of java-decompiler/jd-gui@b3c1ced04e (2026-09-06). Data as JSON: /api/errors/bf341d0d7e5b9f6f. Report an issue: GitHub.