Plugin availability diagnostics
How octl and the Terraform/OpenTofu provider report the plugin availability codes and the deployment queue codes, and how to resolve them.
The standard octl CLI
and the Terraform/OpenTofu provider
contain commands, resources, and data sources for Stellwerk Enterprise plugins,
such as Progressive Rollouts with the plugin ID
dev.stellwerk.progressive-rollouts. Shipping these clients does not install,
enable, or license the plugin on your server. Core commands and Core provider
resources keep working in every plugin state.
Help text and generated documentation mark every plugin-dependent command and resource with the Enterprise requirement and the plugin ID:
$ octl rollout --help
Design and control Progressive Rollouts [Enterprise plugin: dev.stellwerk.progressive-rollouts; installation, enablement and entitlement required]
How clients decide
Before any plugin work, the client asks the server:
GET /orgs/{orgId}/pluginsandGET /orgs/{orgId}/plugins/{pluginId}return the plugin’s state and the operations that Core currently advertises.- If the state or the advertised operations do not permit the command, the client stops with a stable code and an administrator action. It does not contact the plugin.
- Otherwise, the client invokes the operation. The Core gateway checks the state and the license again and can still refuse with the same code.
A server that predates plugin discovery answers the discovery request with
HTTP 404 or 501. Clients report this as plugin_not_installed, not as an
unexplained missing route. HTTP 503 from discovery is reported as
plugin_unavailable. Discovery requires organization_read; without it, the
client reports a normal permission error instead of a plugin code.
Availability codes
| Code | Typical cause | Reads and safety operations | Resolution |
|---|---|---|---|
plugin_not_installed | No installation enabled for the organization, or a server without discovery | Not available | Install the plugin and enable it for the organization. See Install and operate native plugins |
plugin_not_enabled | The installation or the organization’s enablement is disabled, which the plugin reports as not_enabled | Available where the license allows | Enable the installation and the organization through the Plugin Manager API or octl plugin-manager |
plugin_not_entitled | No valid license grant for the required feature, for example after expiry | Available for activated features | Install or renew the license. See License and entitlement trust |
plugin_incompatible | The installed plugin version does not match this Core or client | Not available | Install a plugin version that is compatible with this Core and client, or update the client |
plugin_unavailable | The installation is out of service, the plugin cannot be reached, or the license cannot be evaluated | Not available | Retry later. Check the plugin workload, its readiness, and the Control Plane logs |
After a license expires, octl read commands and the safety commands pause,
cancel, cancel-and-rollback, rollback, and rollback-environment keep
working. The provider keeps refreshing state and reading resources and data
sources. New forward changes fail with plugin_not_entitled. If a forward
request reaches the gateway, the gateway refuses it with HTTP 409 and the same
code.
octl also reports plugin_operation_unavailable when Core does not advertise
an operation in the plugin’s current mode, for example a forward command while
the plugin is in safety_only mode.
CLI examples
octl prints the code first, followed by the plugin name, the plugin ID, and an
action. It exits with status 1.
A server without the plugin:
$ octl get rollouts
Error: plugin_not_installed: Progressive Rollouts (dev.stellwerk.progressive-rollouts) is not installed for this organization
A server that predates plugin discovery:
$ octl get rollouts
Error: plugin_not_installed: Progressive Rollouts (dev.stellwerk.progressive-rollouts) is not installed on this server; ask an administrator to install and enable the Enterprise plugin and obtain a valid licence
A forward command while the plugin is disabled for the organization:
$ octl create rollout --set-yaml @rollout.yaml
Error: plugin_not_enabled: Progressive Rollouts (dev.stellwerk.progressive-rollouts) is not_enabled. Ask an organization administrator to check the plugin installation, activation and licence entitlement.
Discovery that is temporarily unavailable:
$ octl get rollouts
Error: plugin_unavailable: Progressive Rollouts (dev.stellwerk.progressive-rollouts) capability discovery is temporarily unavailable
Terraform and OpenTofu examples
The provider reports every availability code as an error diagnostic with the
summary Required Stellwerk plugin unavailable. The detail starts with the code
and ends with the administrator action that Core returned, or with the
provider’s default action. A plan stops before any plugin work starts:
│ Error: Required Stellwerk plugin unavailable
│
│ plugin_not_enabled: Stellwerk Enterprise plugin Progressive Rollouts
│ (dev.stellwerk.progressive-rollouts) is not_enabled for this organization.
│ Ask an administrator to enable the plugin for this organization.
The default actions are:
| Code | Default action |
|---|---|
plugin_not_installed | Ask a platform administrator to install the plugin and enable it for this organization. |
plugin_not_enabled | Ask an administrator to enable the plugin for this organization. |
plugin_not_entitled | Ask an administrator to install or renew a signed licence for this organization. Reads and safety commands remain available. |
plugin_incompatible | Ask an administrator to install a plugin version that is compatible with this Core and provider. |
plugin_unavailable | Retry later, or ask an administrator to check the plugin workload. |
A plugin that is installed but has no operation routed for the organization
produces plugin_unavailable. An operation that Core advertises with a
different method or mutation flag than the provider expects produces
plugin_incompatible. Unknown future states are never treated as available.
A permission error from discovery stays a normal API error.
Troubleshoot as an administrator
Read the plugin’s state for the affected organization:
curl "${PO_API_URL}/orgs/${ORG_ID}/plugins/dev.stellwerk.progressive-rollouts" \ -H "Authorization: Bearer ${PLATFORM_ORCHESTRATOR_TOKEN}"Compare
statewith the installation and the organization’s enablement fromGET /plugin-installations(octl get plugin-installations), which needsplugin_manager_read. Look at the installation’sorganization_modetoo. An organization that the installation does not list is either not enabled yet (modeselected), or Core could not enable it (modeall) and lists it inpending_organizations, for example because the installation-wide license grant’s organization limit was reached. An organization that opted out has a disabled enablement. Core never enables it again by itself. For a plugin whose IAM capabilities seem to be missing, read the enablement’scapability_registration, which isregistered,pending, orfailedwith adetail.For
not_entitled, inspectentitlement.featuresfor the feature state, trust class, and expiry.For
unavailable, check that the plugin Pods are ready, that the token sidecar has a token, and that the Control Plane can reach the plugin backend. If the installation was never activated, itsavailabilityisunavailableanddiagnostic.codenames why the last activation was refused, for exampleplugin_installation_mismatch. Core reads the plugin status only when you activate. Fix the cause, then activate again.
Deployment queue codes
Deploy and rollback requests that wait in the
deployment queue
are Core behaviour and need no plugin. They report their own stable codes.
octl prints the code and the next step. The provider reports a diagnostic with
the code, and a queued item that never started reports
Queued deployment did not start.
| Code | HTTP | Meaning | Next step |
|---|---|---|---|
environment_busy | 409 | The Environment is busy and the request cannot wait: it asked to fail (--no-queue, or when_busy: reject), an organization token authorized it, or it is a plan-only request while another Runner of the Environment runs | Retry, or let the request queue with a user or service user token. Plan-only requests retry once the Runner finished |
previous_deployment_failed | - | A queued request with halt_on_failure (--halt-on-failure) did not start because the Deployment it waited for failed. It is a reason code of the rejected item, not an HTTP error | The reason_message names the failed Deployment. Fix the cause and submit the request again |
deployment_queue_full | 409 | The Environment already holds the maximum number of waiting items (default 10) | Wait for items to settle, or cancel obsolete ones with octl deployments cancel-queued |
deployment_base_changed | 409 | The Environment’s current Deployment differs from expected_base_deployment_id | Review the new state and submit the request again |
outcome_unreconciled | 409 | A failed plugin-dispatched Deployment may still have a Runner. Queued items of the Environment are rejected with this code | Acknowledge the outcome, then submit the work again |
environment_deleting | 409 | The Environment is being deleted | None. Waiting items are cancelled |
queue_item_dispatching | 409 | A cancellation met a promotion in progress | Read the item again |
queue_item_settled | 409 | The item was already dispatched, rejected, expired, or cancelled | Read the item |
A queue item that was rejected at promotion carries the reason of the failed
check, for example pin_protection or module_version_lifecycle, because Core
resolves the item against the Environment as it is then. octl shows other
conflicts as conflict (<code>): <message>.
Read the queue as an administrator:
curl "${PO_API_URL}/orgs/${ORG_ID}/deployment-queue?project_id=${PROJECT_ID}&env_id=${ENV_ID}&state=queued" \
-H "Authorization: Bearer ${PLATFORM_ORCHESTRATOR_TOKEN}"
Each item shows its position, state, attempts, and last_error. A transient
failure, such as a busy Core or a lease that has not expired, keeps the item
queued and retries with a delay of 5 seconds that doubles up to 2 minutes, until
the item’s time to live ends.