fix(database): skip database request without a database name - #233
Draft
marceloneppel wants to merge 6 commits into
Draft
fix(database): skip database request without a database name#233marceloneppel wants to merge 6 commits into
marceloneppel wants to merge 6 commits into
Conversation
…up scans check_for_invalid_extra_user_roles() and check_for_invalid_database_name() scanned every relation's data bucket including this charm's own application databag. ops forbids a non-leader unit to read its own application databag, so a follower that carries one of the qualifying Blocked statuses (set while it still held leadership) crashes with RelationDataAccessError when a client relation breaks and at least one other client relation remains live - and keeps crashing on every hook retry. Requested fields only ever live in remote databags, so the scans now skip the own app/unit buckets. A regression test emits relation-broken through the framework on a blocked follower so the strict access rules apply. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Carries the database status-cleanup fix for the non-leader own-app databag read. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
…anup paths Parametrize the blocked-follower regression so both cleanup paths are exercised under ops' strict relation data access rules: the direct scan (invalid extra user roles, invalid database name) and unblock_custom_user_errors (forbidden username, missing secret grant). Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
The invalid database name message enters the same cleanup path as the other three qualifying Blocked statuses; assert it explicitly so a future reordering of the cleanup branches cannot drop its coverage. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
A request deferred while the cluster was not ready can replay after its relation has gone away, e.g. a cross-model consumer removed during a Patroni outage. ops re-emits the deferred notice with the dead relation, the request name reads back as absent, and the empty string made it through to create_relation_user_and_database, whose database[-1] raised IndexError. The exception aborts every later hook on the unit, actions included, wedging the leader until the failed hook is resolved. Return early instead: the handler treats a missing result as nothing to do, so the stale notice drains on its next replay. A live requirer can never request an empty name (Juju drops empty databag values), so the guard only affects the replayed-stale-notice path. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Keeps the release line moving for the database-request guard, stacked on the 16.3.7 bump from the status-cleanup scan fix. Signed-off-by: Marcelo Henrique Neppel <marcelo.neppel@canonical.com>
Base automatically changed from
fix/database-manager-own-app-databag-read
to
16/edge
August 31, 2026 11:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue
A
database_requestedevent that was deferred while the cluster was not ready gets replayed by ops on every subsequent dispatch. If the relation has gone away in the meantime — e.g. a cross-model consumer removed during a Patroni outage — ops supplies the dead relation, the remote databag reads back without adatabasekey, andcollect_databasescoerced the missing value to an empty string. The handler then indexed it increate_relation_user_and_database, raising an uncaughtIndexError: string index out of range.ops only drops a deferred notice once its handler returns, so the exception aborted every later hook on the unit — actions included — wedging the leader until the failed hook is resolved.
Solution
Return early from
collect_databaseswhen the request carries no database name, logging a warning instead of coercing the missing value to an empty string. The handler already treats aNonereturn as "nothing to do", so the stale notice drains on its next replay without deferring.A live requirer can never request an empty name: Juju drops a databag key whose value is an empty string, and the provider library only emits
database_requestedwhen that key is added — the guard therefore only affects the replayed-stale-notice path.Checklist