NationalSecurityAgency/ghidra · critical · RuntimeException

Could not instantiate saveable of type

Error message

Could not instantiate saveable of type 

What it means

Thrown by AbstractDBTracePropertyMap.doLoad() during deserialization of a Saveable property value from the trace database. It catches InstantiationException, InvocationTargetException, or SecurityException from the reflective call obj.valueClass.getConstructor().newInstance(), meaning the Saveable's value class could not be instantiated. This is a RuntimeException wrapping the original cause, indicating either a broken Saveable implementation, a constructor that throws, or a security manager restriction.

Source

Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/map/AbstractDBTracePropertyMap.java:445

			byte[] enc = record.getBinaryData(column);
			if (enc == null) {
				setValue(obj, null);
			}
			try {
				Saveable value = getValue(obj);
				if (value == null) {
					value = obj.valueClass.getConstructor().newInstance();
					setValue(obj, value);
				}
				ObjectStorage objStorage = new ObjectStorageStreamAdapter(
					new ObjectInputStream(new ByteArrayInputStream(enc)));
				value.restore(objStorage);
			}
			catch (IOException e) {
				throw new AssertionError(e);
			}
			catch (InstantiationException | InvocationTargetException | SecurityException e) {
				throw new RuntimeException(
					"Could not instantiate saveable of type " + obj.valueClass);
			}
			catch (NoSuchMethodException e) {
				throw new RuntimeException("Saveable must have a default constructor");
			}
		}
	}

	public static class DBTraceStringPropertyMap
			extends AbstractDBTracePropertyMap<String, DBTraceStringPropertyMapEntry> {

		public DBTraceStringPropertyMap(String name, DBHandle dbh, OpenMode openMode,
				ReadWriteLock lock, TaskMonitor monitor, Language baseLanguage, DBTrace trace,
				DBTraceThreadManager threadManager) throws IOException, VersionException {
			super(name, dbh, openMode, lock, monitor, baseLanguage, trace, threadManager,
				DBTraceStringPropertyMapEntry.class, DBTraceStringPropertyMapEntry::new);
		}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Inspect the wrapped cause in the RuntimeException to identify the specific failure (InstantiationException = abstract class, InvocationTargetException = constructor threw, SecurityException = manager blocked access).
  2. Fix the Saveable value class's default constructor so it completes without throwing.
  3. If the Saveable class changed between versions, ensure a migration/upgrade path exists for old trace databases.
  4. If the database is corrupt, restore from a backup or re-create the trace.

Example fix

// before
public class MySaveable implements Saveable {
    public MySaveable() {
        // throws if someField not set
        init(someField);
    }
}

// after
public class MySaveable implements Saveable {
    private Object someField = DEFAULT;
    public MySaveable() {
        // safe default, no exception
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before opening a trace with Saveable properties, verify value classes
// have accessible default constructors
Class<?> valueClass = /* the registered Saveable class */;
try {
    valueClass.getConstructor(); // check no-arg constructor exists
    valueClass.getConstructor().newInstance(); // check it doesn't throw
} catch (Exception e) {
    // fix the class before opening the trace
}

Try / catch

try {
    trace.open(programName, monitor);
} catch (RuntimeException e) {
    if (e.getCause() instanceof InstantiationException ||
        e.getCause() instanceof InvocationTargetException ||
        e.getCause() instanceof SecurityException) {
        // Saveable value class failed to instantiate
        // inspect e.getCause() for details
    }
}

Prevention

When it happens

Trigger: Loading a trace database that contains property map entries whose Saveable value class fails reflective instantiation. This occurs when the valueClass's default constructor throws an exception, the class is abstract, or a SecurityManager blocks reflective access. The error is triggered during trace open/upgrade when doLoad reads binary data from the DB record.

Common situations: After upgrading Ghidra versions where a Saveable class's constructor signature or initialization logic changed and now throws. When a custom Saveable implementation has a buggy default constructor. When running under a restrictive SecurityManager that blocks reflection.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/3858682bb38bc83b. Report an issue: GitHub.