quarkusio/quarkus · error · RuntimeException

OpenShift Miscellaneous API is not available, please add the

Error message

OpenShift Miscellaneous API is not available, please add the openshift-model-miscellaneous module to your classpath

What it means

This is a GraalVM native-image substitution on OpenShiftClientImpl.apiRequestCounts. When the fabric8 openshift-model-miscellaneous module is absent from the classpath, the substitution replaces the real method so that any native-image call throws a RuntimeException telling you the OpenShift Miscellaneous API is unavailable. It exists so failures happen with a clear message instead of an unresolved-class error in native executables.

Source

Thrown at extensions/openshift-client/runtime/src/main/java/io/quarkus/it/openshift/client/runtime/graal/MiscellaneousSubstitutions.java:37

import io.fabric8.openshift.api.model.miscellaneous.helm.v1beta1.HelmChartRepositoryList;
import io.fabric8.openshift.api.model.miscellaneous.helm.v1beta1.ProjectHelmChartRepository;
import io.fabric8.openshift.api.model.miscellaneous.helm.v1beta1.ProjectHelmChartRepositoryList;
import io.fabric8.openshift.api.model.miscellaneous.metal3.v1alpha1.BareMetalHost;
import io.fabric8.openshift.api.model.miscellaneous.metal3.v1alpha1.BareMetalHostList;
import io.fabric8.openshift.api.model.miscellaneous.metal3.v1beta1.Metal3Remediation;
import io.fabric8.openshift.api.model.miscellaneous.metal3.v1beta1.Metal3RemediationList;
import io.fabric8.openshift.api.model.miscellaneous.metal3.v1beta1.Metal3RemediationTemplate;
import io.fabric8.openshift.api.model.miscellaneous.metal3.v1beta1.Metal3RemediationTemplateList;

/**
 * Allows the exclusion of the openshift-model-miscellaneous model without breaking the --link-at-build-time check.
 */
@TargetClass(className = "io.fabric8.openshift.client.impl.OpenShiftClientImpl", onlyWith = MiscellaneousSubstitutions.NoOpenShiftMiscellaneousModel.class)
public final class MiscellaneousSubstitutions {

    @Substitute
    public NonNamespaceOperation<APIRequestCount, APIRequestCountList, Resource<APIRequestCount>> apiRequestCounts() {
        throw new RuntimeException(Constants.ERROR_MESSAGE);
    }

    @Substitute
    public MixedOperation<BareMetalHost, BareMetalHostList, Resource<BareMetalHost>> bareMetalHosts() {
        throw new RuntimeException(Constants.ERROR_MESSAGE);
    }

    @Substitute
    public MixedOperation<CredentialsRequest, CredentialsRequestList, Resource<CredentialsRequest>> credentialsRequests() {
        throw new RuntimeException(Constants.ERROR_MESSAGE);
    }

    @Substitute
    public NonNamespaceOperation<HelmChartRepository, HelmChartRepositoryList, Resource<HelmChartRepository>> helmChartRepositories() {
        throw new RuntimeException(Constants.ERROR_MESSAGE);
    }

    @Substitute

View on GitHub (pinned to e1c734241f)

Solutions

  1. Add io.fabric8:openshift-model-miscellaneous to your dependencies (the quarkus-openshift-client extension pulls it transitively if you need it)
  2. If you don't need Miscellaneous API resources, guard/remove the apiRequestCounts() calls when running in native mode
  3. Rebuild the native image after adding the module so the substitution no longer applies

Example fix

// before (pom.xml)
<dependency><groupId>io.quarkus</groupId><artifactId>quarkus-openshift-client</artifactId></dependency>
// after
<dependency><groupId>io.quarkus</groupId><artifactId>quarkus-openshift-client</artifactId></dependency>
<dependency><groupId>io.fabric8</groupId><artifactId>openshift-model-miscellaneous</artifactId></dependency>
Defensive patterns

Strategy: fallback

Validate before calling

boolean miscModelAvailable;
try {
    Class.forName("io.fabric8.openshift.api.model.miscellaneous.APIRequestCount", false,
        Thread.currentThread().getContextClassLoader());
    miscModelAvailable = true;
} catch (ClassNotFoundException e) {
    miscModelAvailable = false;
}

Type guard

static boolean supportsMiscellaneousApi(OpenShiftClient client) {
    try {
        Class.forName("io.fabric8.openshift.api.model.miscellaneous.apiserver.APIRequestCount", false,
            OpenShiftClient.class.getClassLoader());
        return true;
    } catch (ClassNotFoundException e) {
        return false;
    }
}

Try / catch

try {
    client.apiRequestCounts().list();
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("openshift-model-miscellaneous")) {
        log.warn("Miscellaneous API model missing; skipping APIRequestCount operations");
        return List.of();
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling OpenShiftClient.apiRequestCounts() from code running in a native image where the quarkus-openshift-client extension detected (NoOpenShiftMiscellaneousModel condition) that openshift-model-miscellaneous is not on the classpath.

Common situations: Applications listing/watching APIRequestCount resources on OpenShift 4.x; projects built with a trimmed fabric8 dependency set; upgrading Quarkus/fabric8 and the model module was removed as 'unused' by dependency cleanup.

Related errors


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/19fdaf6f220a7dd4. Report an issue: GitHub.