apache/skywalking · critical · UnexpectedException
Create {stream.builder().getSimpleName()} record DAO failure
Error message
Create {stream.builder().getSimpleName()} record DAO failure. What it means
RecordStreamProcessor.create() reflectively constructs the StorageBuilder for a @Stream Record class (trace segments, alarms, logs...) and obtains an IRecordDAO from the storage plugin. Any reflective instantiation failure is wrapped in this UnexpectedException, which names the failing builder class and aborts startup.
Source
Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/RecordStreamProcessor.java:91
}
RecordPersistentWorker worker = workers.get(record.getClass());
if (worker != null) {
worker.in(record);
}
}
public void create(ModuleDefineHolder moduleDefineHolder, Stream stream, Class<? extends Record> recordClass) throws StorageException {
final StorageBuilderFactory storageBuilderFactory = moduleDefineHolder.find(StorageModule.NAME)
.provider()
.getService(StorageBuilderFactory.class);
final Class<? extends StorageBuilder> builder = storageBuilderFactory.builderOf(recordClass, stream.builder());
StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class);
IRecordDAO recordDAO;
try {
recordDAO = storageDAO.newRecordDao(builder.getDeclaredConstructor().newInstance());
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new UnexpectedException("Create " + stream.builder().getSimpleName() + " record DAO failure.", e);
}
ModelRegistry modelSetter = moduleDefineHolder.find(CoreModule.NAME).provider().getService(ModelRegistry.class);
// Record stream doesn't read data from database during the persistent process. Keep the timeRelativeID == false always.
Model model = modelSetter.add(
recordClass, stream.scopeId(),
new Storage(stream.name(), false, DownSampling.Second),
StorageManipulationOpt.schemaCreateIfAbsent());
ExportRecordWorker exportWorker = new ExportRecordWorker(moduleDefineHolder);
RecordPersistentWorker persistentWorker = new RecordPersistentWorker(moduleDefineHolder, model, recordDAO, exportWorker);
workers.put(recordClass, persistentWorker);
}
}
View on GitHub (pinned to 102af09b4a)
Solutions
- Decode the cause (NoSuchMethodException/InstantiationException/InvocationTargetException) and fix the builder class accordingly — usually add `public Builder() {}`
- Confirm the @Stream(builder=...) value names a public concrete StorageBuilder implementation
- Rebuild everything with 'mvnw clean install' and remove old plugin jars from the deployed oap-libs directory
Example fix
// before
public static class RecordBuilder implements StorageBuilder {
public RecordBuilder(String config) {}
}
// after
public static class RecordBuilder implements StorageBuilder {
public RecordBuilder() {}
} Defensive patterns
Strategy: try-catch
Validate before calling
// assert the builder is reflectively constructible before packaging assertNotNull(MyRecord.Builder.class.getDeclaredConstructor()); assertFalse(Modifier.isAbstract(MyRecord.Builder.class.getModifiers()));
Try / catch
Startup failure — do not catch in production; catch UnexpectedException in plugin integration tests and assert on the underlying reflection cause.
Prevention
- Model custom Record builders on existing ones (e.g. SegmentRecord.Builder) including the public no-arg constructor
- Add a boot-smoke integration test for every custom stream
- Keep plugin compilation target and server-core dependency versions in lockstep
When it happens
Trigger: A custom Record class's builder lacks a public no-arg constructor or is abstract; the builder constructor throws; a third-party storage plugin jar built against a different OAP API cannot be instantiated.
Common situations: Adding custom record types via plugins; storage plugin version drift after a partial OAP upgrade; fat-jar shading or Java module restrictions blocking reflective access.
Related errors
- Create {stream.builder().getSimpleName()} none stream record
- Create {stream.getBuilder().getSimpleName()} metrics DAO fai
- Create {stream.builder().getSimpleName()} none stream record
- Create {stream.builder().getSimpleName()} top n record DAO f
- Metric TTL should be at least 2 days, current value is {}
AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14).
Data as JSON: /api/errors/8e734126c82f3440.
Report an issue: GitHub.