When Rules Are Triggered
Rules run automatically during family syncs or can be triggered manually. Understanding when rules execute helps troubleshoot categorization issues.Manual trigger (user-initiated)
Manual trigger (user-initiated)
- Clicking “Re-apply” on an individual rule in
/settings/rules - Clicking “Apply All” in
/settings/rules - Running the rake task:
bin/rails rules:apply_all[family_id]
During family sync (only active rules)
During family sync (only active rules)
active: true run automatically when a family sync occurs (Family::Syncer.perform_sync):Scheduled syncs:SyncAllJob- runs daily at 2:22 AM for all familiesSyncHourlyJob- runs every hour (for items that opt-in to hourly syncing)
- Provider webhooks (Plaid, etc.) - triggers sync which eventually propagates to family
- Manual sync button on accounts page
- After CSV imports complete (
Importmodel callsfamily.sync_later)
When rules do NOT run
When rules do NOT run
- Manual transaction creation - Only triggers an Account sync (not Family sync)
- Manual transaction editing - Same as above, only Account sync runs
- Inactive rules - Rules with
active: falsenever run automatically, only via manual “Re-apply”
How do I see why a rule run failed?
How do I see why a rule run failed?
- Go to Settings → Debug
- Look for entries with category
rules
Rule run failures not visible in the UI
When rules run asynchronously (during a sync or via a background job), failures are not surfaced in the main UI. If auto-categorization or merchant detection appears to stop working silently, check the debug log.Where are async rule failures logged?
Where are async rule failures logged?
- Go to Settings → Debug
- Filter by the relevant category (e.g.,
rulesorauto_categorize)
Category Rule Popup Behavior
When a user selects a category for a transaction, a popup may appear to create an automatic categorization rule. This popup is intentionally gated by several conditions:When does the popup appear?
When does the popup appear?
- User has not disabled rule prompts (
rule_prompts_disabledis false) - User hasn’t dismissed the popup in the last 24 hours
- The transaction category actually changed
- No existing rule already sets this category for similar transactions
- The transaction has a category assigned
Why isn't the popup showing?
Why isn't the popup showing?
- Recently dismissed: Wait 24 hours after dismissing the popup
- Rule already exists: A matching rule may already be in place
- Prompts disabled: Check if
rule_prompts_disabledis enabled for the user
Sure Doesn’t Work Over HTTPS
If Sure behaves incorrectly or fails when accessed over HTTPS, it’s usually due to missing SSL-related configuration between Nginx and Rails.What causes this issue?
What causes this issue?
When HTTPS is terminated at Nginx but not properly forwarded to the app, Rails may treat requests as HTTP.
How do I fix it?
How do I fix it?
-
Nginx
Ensure HTTPS is forwarded to the upstream app:
-
docker-compose.yml
In the
x-rails-env: &rails_envsection, set:This tells Rails to treat all requests as HTTPS.
Some pages break over HTTPS
Sure uses WebSockets for certain pages. If some pages fail to render correctly or break entirely, this is often caused by missing SSL or upgrade headers in your reverse proxy configuration.What are the symptoms?
What are the symptoms?
How do I fix it?
How do I fix it?
Budget totals do not update after deleting transactions
If a budget still shows spending from a transaction that was already deleted, the most likely cause is a stale aggregate cache. Sure hard-deletes the transaction entry, so the deleted transaction is gone; the stale value can come from cached budget or income totals that were not invalidated by deleting an older entry.What causes this issue?
What causes this issue?
How was it fixed?
How was it fixed?
- The current entry count
- The newest entry
updated_attimestamp
How can maintainers validate it?
How can maintainers validate it?
Family#entries_cache_version, then re-check the affected budget after the next request or cache refresh. The regression test is:Chat fails immediately on a fresh family with a strict OpenAI-compatible provider
Some strict OpenAI-compatible providers (not OpenAI itself) reject chat requests with a schema validation error when a family has no accounts, categories, merchants, tags, or tickers yet.Rule runs fail silently
If auto-categorization or merchant detection rules appear to do nothing, the background job may have failed without surfacing an error in the UI.How do I see rule run failures?
How do I see rule run failures?
rule_run category. Each failed run includes the error class, message, and the rule that triggered it.You can also check worker logs directly:What causes rule runs to fail?
What causes rule runs to fail?
- LLM provider errors — The AI provider returned an error or timed out. Check your
OPENAI_ACCESS_TOKENand provider connectivity. - Auto-categorize provider failures — The provider returned an unexpected response format. These are now propagated and logged rather than silently swallowed.
- Worker not running — Rules run in the background via Sidekiq. Verify the
workercontainer is healthy.
App crashes for a family with an invalid timezone
If a family’s timezone setting contains an unrecognized IANA zone name (for example, after a tzdata rename likeEurope/Kiev → Europe/Kyiv), Sure now falls back to the application default timezone instead of crashing.
Chat fails immediately on a new account with a strict OpenAI-compatible provider
Some strict OpenAI-compatible providers (not OpenAI itself) reject chat requests with a schema validation error when a family has no tags, merchants, or categories yet. This happens because the assistant’s tool schemas includeenum fields built from family data — an empty family produces enum: [], which is invalid JSON Schema.
What causes this?
What causes this?
enum: [] for those fields, which is invalid JSON Schema. OpenAI tolerates it, but strict providers reject the entire request before the model runs.
Family#timezone is a free-text field. If the stored value becomes stale — due to a tzdata rename, a database restore from an older backup, or a direct database edit — the app previously raised an ArgumentError on every request for that family, including the login page.How is it handled now?
How is it handled now?
ActiveSupport::TimeZone before using it. If the value is unrecognized, the app falls back to the default timezone and logs a warning to Settings → Debug under the timezone category. The log is debounced to once per day per family so it does not flood the debug log.To fix the root cause, update the family’s timezone to a valid IANA zone name from Settings → Profile.
Sure builds tool schemas dynamically from your family’s data (account names, categories, merchants, tags, tickers). When none of that data exists yet, the schema contains enum: [], which is invalid JSON Schema. OpenAI tolerates it, but strict OpenAI-compatible providers reject the entire request before the model runs.How was it fixed?
How was it fixed?
string type. This fix applies to both chat tool definitions and the /mcp endpoint’s tools/list.If you are on an older version and cannot upgrade, add at least one account, category, or tag to the family — this populates the enum and avoids the empty-array case.Chat shows “assistant not available” before the model finishes
Self-hosted users running a local model (Ollama, LM Studio, etc.) may see the chat fail with “assistant not available” even though the model is still generating a reply and tokens are being billed.What causes this?
What causes this?
AI_RESPONSE_TIMEOUT, default 90 seconds) that starts when the message is queued. Custom OpenAI-compatible providers use a synchronous code path — nothing renders until the full reply is generated — so the watchdog fires before the model finishes.Tool-using turns make this worse: each tool call adds another full model round. The total time the watchdog must cover is:ASSISTANT_MAX_TOOL_CALL_ITERATIONS=5, OPENAI_REQUEST_TIMEOUT=60), a worst-case turn can take up to 360 seconds of model time — far beyond the 90-second default.How do I fix it?
How do I fix it?
ASSISTANT_MAX_TOOL_CALL_ITERATIONS (reducing the worst-case bound) and then size AI_RESPONSE_TIMEOUT using the formula above.For a local Ollama setup:Why is Sure not running auto-categorization and merchant detection on the same transactions again?
Sure caches AI-generated results to avoid redundant API calls and costs. Once a transaction has been processed by AI rules, it won’t be re-processed unless you explicitly reset the AI cache.Why does Sure cache AI results?
Why does Sure cache AI results?
- Enrichment records - Which attributes were set by AI (category, merchant, etc.)
- Attribute locks - Prevents rules from re-processing already-handled transactions
- Transactions aren’t sent to the LLM repeatedly
- API costs are minimized
- Processing is faster on subsequent rule runs
How do I force Sure to re-process transactions?
How do I force Sure to re-process transactions?
- Go to Settings → Rules
- Click the menu button (three dots)
- Select Reset AI cache
- Confirm the action
ai_cache_reset category. Each run logs when it starts, how many entries were removed per scope, and any records that could not be cleared.When should I reset the AI cache?
When should I reset the AI cache?
- Switching LLM models - Different models may produce better categorizations
- After system updates - New versions may have improved prompts
- Fixing miscategorizations - When AI made systematic errors
- Testing - During development or evaluation of AI features
How do I verify the reset actually ran?
How do I verify the reset actually ran?
- Go to Settings → Debug
- Filter by category
ai_cache_reset
- An info entry when the reset is enqueued from the rules page
- An info entry when the job starts on a worker
- A completion entry with the number of enrichments deleted, broken down by scope
- warn entries for any individual records that could not be cleared
- An error entry if the job could not be enqueued at all