Symptoms
- The instance shows UNREACHABLE, ERROR or REGISTRATION_ERROR under OS Management Hub > Instances.
- The instance never appears in OS Management Hub, or the Oracle Cloud Agent tab says
Plugin OS Management Hub Agent not present for instance .... - Scheduled update jobs stay in Accepted or Waiting and the maintenance window passes with nothing patched.
- Jobs fail with download errors, or the instance still reports pending security advisories after a "successful" run.
This post covers OCI instances. On-premises and third-party cloud instances register through the Management Agent and a management station, which is a different path. For how to design groups, lifecycle environments and schedules, see a patching strategy with OS Management Hub.
Quick triage table
| Symptom | Likely cause | Fix |
|---|---|---|
Plugin ... not present or failed to start osmh-agent | Missing dynamic group rule or policy | Section 3 |
Log shows 404 NotAuthorizedOrNotFound | Instance compartment not in the dynamic group | Section 3 |
Log shows 400 MissingParameter / "Registration profile is required" | No profile that matches the OS and architecture | Section 4 |
Log shows 409 Conflict ... osFamily | Profile is for a different OS version | Section 4 |
Log shows started oci-osmh under unregistered mode | Instance was unregistered earlier | Section 4 |
| UNREACHABLE after working fine | Route to the service lost, agent stopped, clock skew | Sections 2, 5 |
| Jobs stuck in Accepted | Instance hasn't checked in | Section 5 |
| Job download errors | Software source not available or repo issue | Section 6 |
1. Find the affected instances
List everything that isn't healthy in a compartment:
C=ocid1.compartment.oc1..aaaa
for s in UNREACHABLE ERROR REGISTRATION_ERROR WARNING; do
echo "== $s"
oci os-management-hub managed-instance list -c "$C" --status "$s" --all \
--query 'data.items[].{name:"display-name",id:id,agent:"agent-version"}' --output table
done
Get details for one instance, including when it last checked in:
oci os-management-hub managed-instance get --managed-instance-id ocid1.instance.oc1..xxxx \
--query 'data.{status:status,lastContact:"time-last-contact",profile:profile,os:"os-family"}'
Field names in the output vary slightly by CLI version; run without --query if a field comes back empty.
Check the plugin state from the Compute side:
oci instance-agent plugin list -c "$C" --instanceagent-id ocid1.instance.oc1..xxxx \
--query 'data[?name==`OS Management Hub Agent`]' --output table
If the plugin is STOPPED or missing, check that it is enabled on the instance (Instance details > Oracle Cloud Agent). The plugin needs Oracle Cloud Agent running on the instance.
2. Can the instance reach the service?
OCI instances talk to osmh.<region>.oci.<realm-domain>. From the instance:
curl -s -H "Authorization: Bearer Oracle" http://169.254.169.254/opc/v2/instance/regionInfo > /tmp/ri.json
REGION=$(jq -r .regionIdentifier /tmp/ri.json)
DOMAIN=$(jq -r .realmDomainComponent /tmp/ri.json)
curl -s "https://osmh.$REGION.oci.$DOMAIN" >/dev/null && echo Success || echo Failure
A reachable endpoint answers with a NotAuthorizedOrNotFound JSON body; that is fine, it means the network path works. A timeout or a name resolution error means the path is broken.
For instances in private subnets:
- The subnet's route table needs a rule to a service gateway for "All services in Oracle Services Network".
- Egress on 443 must be allowed by the security list or NSG.
- If you use custom DNS, it must resolve
*.oci.oraclecloud.com(forward to the VCN resolver).
Tip
If a whole subnet went UNREACHABLE at once, look for a recent route table, NSG or service gateway change in Audit before touching the instances.
3. Policies and dynamic group
The instance authenticates as an instance principal, so it needs to be in a dynamic group and that group needs the OSMH policy.
Dynamic group matching rule (match any). Add every compartment that holds instances; dynamic groups do not inherit child compartments:
ANY {instance.compartment.id='ocid1.compartment.oc1..prod', instance.compartment.id='ocid1.compartment.oc1..prod-app'}
Instance policy:
allow dynamic-group osmh-instances to {OSMH_MANAGED_INSTANCE_ACCESS} in tenancy where request.principal.id = target.managed-instance.id
Admin policy:
allow group osmh-admins to manage osmh-family in tenancy
If the dynamic group lives in a non-default identity domain, prefix it: allow dynamic-group 'MyDomain'/'osmh-instances' to .... A missing domain prefix is a common reason for failed to start osmh-agent messages.
Policy changes can take a few minutes to propagate. After fixing, restart the agent (section 5) instead of waiting for the next check-in.
4. Registration profile problems
On the instance, read the agent log:
sudo grep -i -e "error code" -e "unregistered" \
/var/lib/oracle-cloud-agent/plugins/oci-osmh/osmh-agent/stateDir/log/osmh-agent.log | tail -20
- 400 MissingParameter: there's no profile that matches this instance's OS version and architecture in the compartment. Create one, or set one with Set profile on the instance page.
- 409 Conflict with
osFamily: the profile is for Oracle Linux 7 and the instance is Oracle Linux 8, or similar. Pick a matching profile. - Unregistered mode: the instance was unregistered before. Remove the marker file, then restart the agent:
sudo rm /var/lib/oracle-cloud-agent/plugins/oci-osmh/osmh-agent-unregister
sudo systemctl restart oracle-cloud-agent
Arm (Ampere) instances need a profile with the AARCH64 architecture; an x86 profile won't match.
5. Agent stopped, clock skew or no check-in
Jobs stay in Accepted until the instance checks in and picks them up. Check the agent on the instance:
sudo systemctl status oracle-cloud-agent
ps -ef | grep -i osmh | grep -v grep
sudo tail -50 /var/log/oracle-cloud-agent/plugins/oci-osmh/oci-osmh.log
sudo grep -i -e error -e fail /var/lib/oracle-cloud-agent/plugins/oci-osmh/osmh-agent/stateDir/log/*.log | tail -20
Restart it:
sudo systemctl restart oracle-cloud-agent
Check the clock. More than about five minutes of skew causes signed requests to fail:
date -u
curl -s --head "https://osmh.$REGION.oci.$DOMAIN" | grep -i '^date'
chronyc tracking
Oracle Linux on OCI uses 169.254.169.254 as its NTP source by default. If someone replaced chrony.conf with internal servers that are unreachable, fix that first.
Other things that stop check-ins:
/varfull, so the agent can't write state:df -h /var.- The instance was stopped during the window. Jobs don't run on stopped instances.
- An old OS Management Service Agent plugin still enabled alongside the hub plugin. Disable the old plugin; only the OS Management Hub Agent should be enabled.
6. Job failed or did nothing
List recent failed work requests and read their errors:
oci os-management-hub work-request list -c "$C" --compartment-id-in-subtree true \
--status FAILED --time-created-gte 2026-10-20T00:00:00Z --all \
--query 'data.items[].{id:id,op:"operation-type",time:"time-created"}' --output table
oci os-management-hub work-request list-errors --work-request-id ocid1.osmhworkrequest.oc1..xxxx
oci os-management-hub work-request list-logs --work-request-id ocid1.osmhworkrequest.oc1..xxxx
Common causes:
| Error pattern | Cause | Fix |
|---|---|---|
| Package download errors | Software source not attached, or a custom/versioned source missing the package | Attach the vendor source or rebuild the custom source |
| Dependency or conflict errors | Locally installed RPMs or third-party repos conflict with OSMH sources | Run sudo dnf check-update on the box to see the conflict; remove or exclude the package |
Another app is currently holding the yum lock | A manual dnf or another tool running | Wait or stop the other process, rerun the job |
| Succeeded but advisories still pending | Kernel installed, not yet rebooted | Reboot, or use Ksplice |
Find instances that are patched but waiting for a reboot:
oci os-management-hub managed-instance list -c "$C" --is-reboot-required true --all \
--query 'data.items[]."display-name"'
To retry a failed job after fixing the cause, use the Rerun action on the job, or oci os-management-hub work-request rerun (check --help for the parameters in your CLI version).
Warning
Don't fix a stuck job by running
dnf update -yby hand across the fleet. You lose the lifecycle environment control and the OSMH record of what was installed, and you can pull packages that haven't passed testing.
Prevent it next time
- Add new compartments to the OSMH dynamic group as part of compartment creation. Put the rule in Terraform next to the compartment.
- Create an alarm or a scheduled CLI check for instances in
UNREACHABLEorREGISTRATION_ERROR, and report it before each patch window rather than after. - Keep a service gateway route in every private subnet that hosts managed instances.
- Leave NTP on the OCI default unless you have a reason to change it.
- Include the OSMH plugin in your image build and instance configurations, so new instances register with the right profile at launch.
- Review failed work requests the morning after each window; don't wait for the next vulnerability report.