apache/skywalking · critical · UnexpectedException

Create {stream.builder().getSimpleName()} top n record DAO f

Error message

Create {stream.builder().getSimpleName()} top n record DAO failure.

What it means

TopNStreamProcessor.create() reflectively instantiates the StorageBuilder of a @Stream TopN class and requests an IRecordDAO for it. Reflection failures — missing public no-arg constructor, abstract builder, constructor that throws — are wrapped as this UnexpectedException ('top n record DAO failure'), failing OAP startup.

Source

Thrown at oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/worker/TopNStreamProcessor.java:89

        }
        this.topNWorkerReportCycle = topNWorkerReportCycle;
    }

    public void create(ModuleDefineHolder moduleDefineHolder,
                       Stream stream,
                       Class<? extends TopN> topNClass) throws StorageException {
        final StorageBuilderFactory storageBuilderFactory = moduleDefineHolder.find(StorageModule.NAME)
                                                                              .provider()
                                                                              .getService(StorageBuilderFactory.class);
        final Class<? extends StorageBuilder> builder = storageBuilderFactory.builderOf(topNClass, 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() + " top n record DAO failure.", e);
        }

        ModelRegistry modelSetter = moduleDefineHolder.find(CoreModule.NAME).provider().getService(ModelRegistry.class);
        // Top N metrics doesn't read data from database during the persistent process. Keep the timeRelativeID == false always.
        Model model = modelSetter.add(
            topNClass, stream.scopeId(),
            new Storage(stream.name(), false, DownSampling.Second),
            StorageManipulationOpt.schemaCreateIfAbsent());

        TopNWorker persistentWorker = new TopNWorker(
            moduleDefineHolder, model, topSize, topNWorkerReportCycle * 60 * 1000L, recordDAO, topNClass);
        persistentWorkers.add(persistentWorker);
        workers.put(topNClass, persistentWorker);
    }

    @Override
    public void in(TopN topN) {

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Add a public no-arg constructor to the builder class named in the @Stream annotation (most common cause: only a parameterized constructor exists)
  2. Make sure the class is public and non-abstract and implements StorageBuilder
  3. Rebuild the plugin against the current OAP version and verify a single plugin version in oap-libs

Example fix

// before
public static class TopNBuilder implements StorageBuilder {
    public TopNBuilder(int size) {}
}
// after
public static class TopNBuilder implements StorageBuilder {
    public TopNBuilder() {}
}
Defensive patterns

Strategy: try-catch

Validate before calling

assertNotNull(MyTopN.Builder.class.getDeclaredConstructor());
assertTrue(StorageBuilder.class.isAssignableFrom(MyTopN.Builder.class));

Try / catch

Fail fast at startup; in test code catch UnexpectedException, unwrap getCause(), and fail with a message naming the builder class defect.

Prevention

When it happens

Trigger: Declaring a custom TopN stream whose builder class cannot be reflectively instantiated with newInstance(); storage plugin jar incompatibility making the DAO creation path fail.

Common situations: Custom top-N (e.g. service slow endpoint tracking) plugins with incorrect builder declarations; mixing OAP versions between server-core and a custom storage extension.

Related errors


AI-assisted analysis of apache/skywalking@102af09b4a (2026-08-14). Data as JSON: /api/errors/627db744c69cbaf7. Report an issue: GitHub.