apache/skywalking · critical · UnexpectedException

Create {stream.getBuilder().getSimpleName()} metrics DAO fai

Error message

Create {stream.getBuilder().getSimpleName()} metrics DAO failure.

What it means

MetricsStreamProcessor.create() reflectively builds the StorageBuilder for a metrics class and obtains an IMetricsDAO from the configured storage plugin. Wrapped reflection failures (missing/throwing/inaccessible no-arg builder constructor, abstract builder) are rethrown as this UnexpectedException, aborting OAP startup for that stream.

Source

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

    private void create(ModuleDefineHolder moduleDefineHolder,
                        StreamDefinition stream,
                        Class<? extends Metrics> metricsClass,
                        MetricStreamKind kind,
                        StorageManipulationOpt opt) throws StorageException {
        final StorageBuilderFactory storageBuilderFactory = moduleDefineHolder.find(StorageModule.NAME)
                                                                              .provider()
                                                                              .getService(StorageBuilderFactory.class);
        final Class<? extends StorageBuilder> builder = storageBuilderFactory.builderOf(
            metricsClass, stream.getBuilder());

        StorageDAO storageDAO = moduleDefineHolder.find(StorageModule.NAME).provider().getService(StorageDAO.class);
        IMetricsDAO metricsDAO;
        try {
            metricsDAO = storageDAO.newMetricsDao(builder.getDeclaredConstructor().newInstance());
        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException |
                 InvocationTargetException e) {
            throw new UnexpectedException("Create " + stream.getBuilder().getSimpleName() + " metrics DAO failure.", e);
        }

        ModelRegistry modelSetter = moduleDefineHolder.find(CoreModule.NAME).provider().getService(ModelRegistry.class);
        DownSamplingConfigService configService = moduleDefineHolder.find(CoreModule.NAME)
                                                                    .provider()
                                                                    .getService(DownSamplingConfigService.class);
        TTLStatusQuery ttlStatusQuery = moduleDefineHolder.find(CoreModule.NAME)
                                                          .provider()
                                                          .getService(TTLStatusQuery.class);

        MetricsPersistentWorker hourPersistentWorker = null;
        MetricsPersistentWorker dayPersistentWorker = null;

        MetricsTransWorker transWorker = null;

        final MetricsExtension metricsExtension = metricsClass.getAnnotation(MetricsExtension.class);
        /**
         * All metrics default are `supportDownSampling` and `insertAndUpdate`, unless it has explicit definition.

View on GitHub (pinned to 102af09b4a)

Solutions

  1. Read the cause exception: NoSuchMethodException -> add public no-arg constructor; InstantiationException -> make builder concrete; InvocationTargetException -> fix the exception thrown inside the builder constructor
  2. Verify the @Stream annotation's builder class is public, top-level-accessible, and compiled against the current server-core
  3. Clean and rebuild: 'mvnw clean install' to remove stale jars, and confirm no duplicate plugin versions in the distribution's oap-libs

Example fix

// before
@Stream(name = "my_metric", builder = MyMetric.Builder.class, ...)
public static class Builder { /* only a private constructor */ }
// after
public static class Builder implements StorageBuilder {
    public Builder() {}
    // storageBuilder0 / entity2Storage implementations
}
Defensive patterns

Strategy: try-catch

Validate before calling

// plugin self-check at test time
assertNotNull(MyMetric.Builder.class.getDeclaredConstructor()); // must exist and be public
assertTrue(StorageBuilder.class.isAssignableFrom(MyMetric.Builder.class));

Try / catch

At startup this must fail fast (do not catch); in integration tests, catch UnexpectedException, unwrap with getCause(), and assert it identifies the exact builder defect (NoSuchMethodException vs InvocationTargetException).

Prevention

When it happens

Trigger: A custom Metrics class's @Stream(builder=...) points to a builder without a public no-arg constructor, an abstract class, or a constructor that throws; or a storage plugin jar version mismatch makes instantiation fail.

Common situations: Adding a custom OAL metrics function/plugin and misdeclaring its builder; deploying OAP with mixed-version storage plugin jars in oap-libs; a shaded/fat jar breaking reflective access under a restrictive module path.

Related errors


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