Symptom
The change happened, but the rule did nothing. No email arrived, the function did not run, or the stream stayed empty. The rule shows as active and nothing in the Console reports an error.
An event is emitted, matched by the rule, then delivered to the action. Find the failing stage first.
| What you see | Likely cause | Fix |
|---|---|---|
| Rule not matching, and the resource is in another compartment | Rule sits in a sibling or child compartment | Move the rule up to a common parent |
| Rule not matching on object uploads or deletes | Object events are off on the bucket | oci os bucket update --object-events-enabled true |
| Rule not matching, compartment is right | Wrong event type or a filter field the event lacks | Capture a real payload and copy from it |
| Rule not matching, resource is in another region | Rule was created in a different region | Create the rule in that region |
| Matched, but delivery failures | Action disabled, or target or permissions wrong | Check the action state and the target |
| Delivered, but no email | Subscription is still pending | Confirm the subscription |
| Delivered, function did nothing useful | Error inside the function | Read the function logs |
Check 1: rule and action state
RULE=ocid1.eventrule.oc1..xxxx
oci events rule get --rule-id $RULE --query 'data.{
name:"display-name", state:"lifecycle-state", enabled:"is-enabled",
compartment:"compartment-id", condition:condition}'
oci events rule get --rule-id $RULE --query 'data.actions.actions[].{
type:"action-type", enabled:"is-enabled",
state:"lifecycle-state", message:"lifecycle-message"}' --output table
The rule and each action have their own enabled flag, so check both. Also note which region your CLI profile points to. If rule get returns a not-found error, the rule may be in another region, or you may not have read access.
Turn a disabled rule back on:
oci events rule update --rule-id $RULE --is-enabled true
Check 2: Events metrics show which stage failed
The Events service publishes metrics to the oci_cloudevents namespace without any setup:
| Metric | Meaning |
|---|---|
PublishedEvents | Events emitted |
MatchedEvents | Events a rule matched |
DeliverySucceedEvents | Events delivered to actions |
DeliveryFailedEvents | Unsuccessful deliveries |
Query them for the rule's compartment over a window that includes the change:
C=ocid1.compartment.oc1..xxxx
START=$(date -u -d '6 hours ago' +%Y-%m-%dT%H:%M:%SZ)
END=$(date -u +%Y-%m-%dT%H:%M:%SZ)
for M in MatchedEvents DeliverySucceedEvents DeliveryFailedEvents; do
echo "== $M"
oci monitoring metric-data summarize-metrics-data -c $C \
--namespace oci_cloudevents --query-text "$M[5m].sum()" \
--start-time $START --end-time $END \
--query 'data[].{dims:dimensions, points:"aggregated-datapoints"}'
done
The dimensions output shows which rule each series belongs to. Read the result like this:
- No match for your rule: go to Checks 3 to 5.
- Matched, with delivery failures: go to Check 6.
- Matched and delivered: the problem is after the action. Go to Check 6 for subscriptions and function logs.
Empty output is not proof of zero events. You may need access to the monitoring service and the rule, and the query must target the right compartment and region.
Check 3: scope and region
A rule only matches events from resources in its own compartment and that compartment's children. A rule in prod-app will not see a resource in prod-network, even if both have the same parent.
Rules are also regional, so a rule in us-ashburn-1 does not act on a change in eu-frankfurt-1. Create the rule in each region you need to cover.
IAM changes are made in the home region. Create rules for IAM event types there, then make a harmless test change to confirm they fire.
If a resource was recently moved to another compartment, the old rule may no longer cover it. See Moving OCI resources between compartments.
Before you change the rule, confirm the API call really happened and where:
oci audit event list -c $C --start-time $START --end-time $END --all \
--query 'data[].{type:"event-type", time:"event-time", name:data."resource-name", compartment:data."compartment-name"}' \
--output table
Audit and rule type names differ. Audit may show com.oraclecloud.ComputeApi.TerminateInstance, while the rule type is com.oraclecloud.computeapi.terminateinstance.end. Don't copy one into the other.
Check 4: object events are off
Buckets emit events for bucket changes by default, but objects do not. A rule on com.oraclecloud.objectstorage.createobject stays silent until you enable this on the bucket:
oci os bucket get --bucket-name my-bucket --query 'data."object-events-enabled"'
oci os bucket update --bucket-name my-bucket --object-events-enabled true
Check 5: the condition doesn't match
The condition is JSON. These rules from Oracle's filter documentation cause most mistakes:
- The event must contain every field named in the filter, with the same nesting. A filter on a field the event lacks never matches.
- An array matches if any of its values match.
*works in values only, not keys. A value of only*matches any value but not null.- A period has no special meaning.
{}matches everything in the compartment and its children.
Common event type errors:
.beginversus.end: long-running operations have both. A rule on.enddoes not fire when the operation starts.- Case: most types are lowercase, but some services use mixed case, such as
com.oraclecloud.computeapi.ChangeComputeCapacityReservation.begin. Copy exact names from the Console rule builder or the event types reference. - Tags: the payload field in Oracle's event reference is
freeFormTags, with a capital F. An untagged resource has nothing to match.
Capture a real payload
Stop guessing at field names. Create a short-lived broad rule that sends to a debug topic, then trigger the change:
oci events rule create -c $C --display-name debug-events-delete-me \
--is-enabled true \
--condition '{"eventType":"com.oraclecloud.objectstorage.*bucket"}' \
--actions '{"actions":[{"actionType":"ONS","isEnabled":true,"topicId":"'"$DEBUG_TOPIC"'"}]}'
Change the wildcard to fit the service you're testing. Compare the emailed JSON with your condition, field by field, then fix the real rule:
oci events rule update --rule-id $RULE --force --condition '<corrected-json>'
Warning
A broad rule can flood a topic, and Notifications limits delivery rates per protocol. Use a dedicated debug topic, keep the wildcard narrow, and delete the rule when you finish:
oci events rule delete --rule-id <debug-rule-ocid> --force. Rules also count against a tenancy limit, so check the current limits.
Check 6: the action
Notifications
oci ons subscription list -c $C --topic-id $TOPIC --all \
--query 'data[].{protocol:protocol, endpoint:endpoint, state:"lifecycle-state"}' --output table
oci ons message publish --topic-id $TOPIC --title "delivery test" --body "delivery test"
Notifications only delivers to active subscriptions, so a pending email subscription receives nothing until someone confirms it. If the test message arrives but rule events do not, the problem is in the rule. If the test doesn't arrive, it's the topic or subscription. Also check spam filters.
Functions
oci fn function invoke --function-id $FN --file "-" --body ""
If this fails, fix the function first. If it works, enable the application's service log and read it while you trigger a real event. A delivered event shows only that the action was reached, not that your code did its job. The function also needs its own dynamic group and policies for any OCI API it calls.
Permissions
Oracle documents statements like these for the group that manages rules. The full list, including Streaming and cross-tenancy delivery, is on its Events and IAM Policies page:
allow group RuleAdmins to manage cloudevents-rules in tenancy
allow group RuleAdmins to use ons-topic in tenancy
allow group RuleAdmins to manage function-family in tenancy
allow group RuleAdmins to use virtual-network-family in tenancy
Prevent it next time
Alarm on delivery failures, and send that alarm to a different topic so a broken topic can't hide its own failure:
oci monitoring alarm create -c $C --display-name events-delivery-failed \
--metric-compartment-id $C --namespace oci_cloudevents \
--query-text 'DeliveryFailedEvents[5m].sum() > 0' \
--severity WARNING --is-enabled true \
--destinations '["'"$OPS_TOPIC"'"]'
- Test every new rule with a real change.
- Enable object events in the same Terraform or script that creates the bucket.
- Review rule scope when you reorganize compartments.