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)
Rules can be manually triggered in the following ways:
- 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)
Rules with
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
Rules are not triggered in these scenarios:
- 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”
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?
The popup only shows when all of these conditions are met:
- 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?
Check these common reasons:
- 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?
Sure relies on correct protocol headers to determine whether a request is secure.
When HTTPS is terminated at Nginx but not properly forwarded to the app, Rails may treat requests as HTTP.
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?
Apply the following configuration changes:
-
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?
You may see pages partially load, fail completely, or errors similar to:This indicates that the WebSocket upgrade request is not being forwarded correctly.
How do I fix it?
How do I fix it?
Ensure your Nginx configuration includes the required WebSocket headers:These headers allow Nginx to properly handle WebSocket upgrade requests over HTTPS.
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?
Budget totals are derived from entry aggregation queries. Older versions of Sure used the most recent entry update timestamp as part of the cache key, which meant deleting an older transaction could leave the cache key unchanged.
How was it fixed?
How was it fixed?
The entry aggregate cache version now includes both:
- The current entry count
- The newest entry
updated_attimestamp
How can maintainers validate it?
How can maintainers validate it?
Confirm the installed version includes the cache invalidation fix for
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 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?
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?
Empty
enum arrays are now pruned from tool schemas before they are sent. An empty enum falls back to a plain string type, which is valid. This fix applies to both chat tool definitions and the /mcp endpoint’s tools/list response.If you are on an affected version, upgrade to the latest release. No configuration change is needed.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?
Sure uses a whole-turn watchdog (With the defaults (
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?
The most effective approach is to lower You can also set Chat Response Timeout from Settings → Self-Hosting → AI Provider in the UI. The environment variable takes precedence.See Chat response timeout for full sizing guidance.
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:Sure NDJSON import fails on a full export
Importing a fullall.ndjson export can fail preflight validation even when the file is valid.
Import fails because a rule has no name
Import fails because a rule has no name
Rules with a
null name are valid in Sure’s data model, but older preflight logic required name to be present. This caused a single unnamed rule to block the entire import.This is fixed in the current release. If you are on an older version, upgrade and re-run the import.Import fails due to a rejected transfer referencing a deleted transaction
Import fails due to a rejected transfer referencing a deleted transaction
A
RejectedTransfer row whose referenced transaction was later deleted previously raised a hard error during preflight, preventing the import from proceeding.The importer now treats these references as advisory: the orphaned RejectedTransfer row is skipped and counted as a warning rather than blocking the import. The data.warnings array in the preflight response will include a human-readable message for each skipped row.If you see warnings about missing references after upgrading, the import will still complete successfully — the orphaned rows are simply omitted.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?
When AI rules process transactions, Sure stores:
- 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?
To have AI rules re-process transactions, you need to reset the AI cache:
- Go to Settings → Rules
- Click the menu button (three dots)
- Select Reset AI cache
- Confirm the action
When should I reset the AI cache?
When should I reset the AI cache?
Common scenarios for resetting the 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