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);
}
@SubstituteView on GitHub (pinned to e1c734241f)
Solutions
- Add io.fabric8:openshift-model-miscellaneous to your dependencies (the quarkus-openshift-client extension pulls it transitively if you need it)
- If you don't need Miscellaneous API resources, guard/remove the apiRequestCounts() calls when running in native mode
- 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
- Always declare io.fabric8:openshift-model-miscellaneous explicitly if you touch Miscellaneous API resources
- Smoke-test native builds for every client method used, since substitutions only fail at native runtime
- Never 'clean up' fabric8 model dependencies without checking which OpenShiftClient accessors the code calls
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
- OpenShift Operator API is not available, please add the open
- Could not read class path resources having path '${resourceP
- Build:%s is no longer present!
- Build:%s has no status!
- Build:%s cancelled!
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/19fdaf6f220a7dd4.
Report an issue: GitHub.