Issue Description
In Stalwart 0.16.22, update_spam_rules() can return TaskResult::Success even when importing or activating the ruleset fails.
Reload failures are not reflected in the task outcome:
- Err returned by reload_registry() is logged, but execution continues.
- Ok(ReloadResult) containing configuration errors is ignored entirely, without checking has_errors().
Object-write failures handled by the failed counter also do not affect the final result. This pattern applies to SpamRule, SpamDnsblServer, SpamTag, HttpLookup, MemoryLookupKey and SpamFileExtension.
The function then emits RulesUpdated and returns TaskResult::Success(vec!).
This concerns those specific error paths. Other errors, including failures to fetch or parse the ruleset, already return failure.
Expected Behavior
The task should report a non-success outcome when any object import is counted as failed or when required settings/lookup activation fails.
Both Err and Ok(ReloadResult) with non-empty errors should be handled.
A successful task outcome should indicate that the import and required activation completed, rather than merely that execution reached the end of the function.
Actual Behavior
The task reports success despite the handled failures described above.
In the activation-failure case, objects may already have been written to the registry while the running server retains its previous settings or lookup stores. Stored configuration and active configuration can therefore differ even though the update task reports success.
For object-import failures, the failed count appears in the logged tally, but the task outcome remains Success.
Reproduction Steps
Suggested fault-injection tests against v0.16.22;
A. Reload returns Err
- Supply a valid ruleset containing a new SpamRule.
- Allow insertion to succeed, setting reload_settings=true.
- Inject an Err from the subsequent reload_registry() call.
- Inspect the task result.
Expected: non-success. Current code path: the error is logged, followed by Success.
B. Reload returns configuration errors
- Repeat the successful insertion.
- Make reload_registry() return Ok(ReloadResult) with non-empty errors and without activating the new configuration.
- Inspect the task result.
Expected: non-success. Current code path: the result is discarded, followed by Success.
Repeat the activation tests for lookup-store reloading.
C. Object import is counted as failed
- Supply a valid ruleset.
- Inject an object-write result that reaches a branch incrementing stats.failed.
- Allow the remaining operations to complete.
- Inspect the tally and task result.
Expected: non-success. Current code path: failed is incremented, but the task returns Success.
Relevant Log Output
No runtime logs are attached. This is a source-level finding; the reproduction steps describe proposed fault-injection tests.
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
Internal
Additional Context
Object-import failure counters:
Reload handling and final Success:
Reload activation guards and ReloadResult error handling:
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on