How to Enable and Use SQLite Logging in n8n for Debugging

Step by Step Guide to Enable and Use SQLite Logging in n8n for Debugging

 

 

Who this is for: n8n administrators and workflow developers who need to diagnose SQLite‑related failures in production or staging environments. For a complete guide on managing SQLite in n8n, including errors, performance, and migration, check out our n8n SQLite pillar guide.


Quick Diagnosis

Step Action Command / Setting Expected Result
1 Set log level to debug for SQLite N8N_LOG_LEVEL=debug (env) n8n prints all SQLite statements to stdout
2 Enable file‑based SQLite logs N8N_SQLITE_LOG_PATH=/var/log/n8n/sqlite.log (env) Log file created, rotated automatically
3 Restart the n8n service docker restart n8n or systemctl restart n8n New settings take effect
4 Reproduce the error in your workflow Run the failing node Corresponding SQL statements appear in the log
5 Search the log for the error code grep -i "SQLITE_.*" /var/log/n8n/sqlite.log Identify the exact SQLite error (e.g., SQLITE_BUSY)
6 Apply the corrective action (e.g., increase timeout, fix schema) Follow the “Common SQLite Errors” table below Workflow runs without error

Featured snippet ready: To enable SQLite logging in n8n, set N8N_LOG_LEVEL=debug and N8N_SQLITE_LOG_PATH environment variables, then restart n8n. The log file will contain every SQL statement and SQLite error code, which you can grep to pinpoint issues. Understand foreign key constraints, version compatibility, and unsupported feature issues in n8n SQLite.


1. Why SQLite Logging Matters in n8n

n8n stores workflow state, execution metadata, and credential data in a local SQLite database by default. When a node fails with a cryptic “SQLITE_….” error, the only reliable way to understand the root cause is to inspect the raw SQL that n8n sent to SQLite.

  • Visibility into each SELECT, INSERT, UPDATE, and PRAGMA call.
  • Error codes (SQLITE_BUSY, SQLITE_CONSTRAINT, …) tied to the exact statement.
  • Performance clues – long‑running queries appear with timestamps.

EEFA note: Never leave N8N_LOG_LEVEL=debug permanently on in production; it can expose credentials and flood storage. Use file‑based logging with rotation and restrict file permissions (chmod 600).


2. Enabling SQLite Logging

2.1. Docker (environment variables)

Set the required variables and run the container.

# Export variables for clarity (optional)
export N8N_LOG_LEVEL=debug
export N8N_SQLITE_LOG_PATH=/var/log/n8n/sqlite.log
export N8N_SQLITE_LOG_MAX_SIZE=10485760   # 10 MiB
export N8N_SQLITE_LOG_MAX_FILES=5
docker run -d \
  -e N8N_LOG_LEVEL=$N8N_LOG_LEVEL \
  -e N8N_SQLITE_LOG_PATH=$N8N_SQLITE_LOG_PATH \
  -e N8N_SQLITE_LOG_MAX_SIZE=$N8N_SQLITE_LOG_MAX_SIZE \
  -e N8N_SQLITE_LOG_MAX_FILES=$N8N_SQLITE_LOG_MAX_FILES \
  -v /var/log/n8n:/var/log/n8n \
  n8nio/n8n:latest

2.2. Systemd service (Ubuntu)

Create the service unit with the logging variables.

# /etc/systemd/system/n8n.service
[Unit]
Description=n8n workflow automation
After=network.target

[Service]
Environment="N8N_LOG_LEVEL=debug"
Environment="N8N_SQLITE_LOG_PATH=/var/log/n8n/sqlite.log"
Environment="N8N_SQLITE_LOG_MAX_SIZE=10485760"
Environment="N8N_SQLITE_LOG_MAX_FILES=5"
ExecStart=/usr/local/bin/n8n
Restart=on-failure
User=n8n
Group=n8n

[Install]
WantedBy=multi-user.target
# Reload systemd, enable and start n8n
systemctl daemon-reload
systemctl enable --now n8n

EEFA warning: Ensure /var/log/n8n exists and is owned by the n8n user; otherwise SQLite logs will be silently dropped.

2.3. .env file (non‑Docker)

Create a .env file alongside the n8n binary.

# .env
N8N_LOG_LEVEL=debug
N8N_SQLITE_LOG_PATH=./logs/sqlite.log
N8N_SQLITE_LOG_MAX_SIZE=10485760
N8N_SQLITE_LOG_MAX_FILES=5

Start n8n with dotenv support:

npm install -g dotenv-cli   # if not already installed
dotenv -e .env n8n

3. Interpreting the Log Entries

n8n writes SQLite logs as JSON‑lines, making them easy to pipe into jq.

3.1. Typical log line (compact view)

{"timestamp":"2025-12-24T14:32:07.123Z","level":"debug","source":"sqlite","msg":"Executed query","sql":"INSERT INTO \"execution_entity\" (\"id\",\"workflowId\",\"startedAt\") VALUES (?,?,?)","params":["c1a2b3d4","5f6e7d8c","2025-12-24T14:32:07.123Z"],"durationMs":3}
  • timestamp – When the query ran.
  • sql – Raw statement.
  • params – Parameter array (useful for data‑type mismatches).
  • durationMs – Execution time; > 100 ms may indicate lock contention.

3.2. Filtering for errors

grep -i '"msg":"Error"' /var/log/n8n/sqlite.log | jq .

Sample error entry (compact):

{"timestamp":"2025-12-24T14:45:22.987Z","level":"debug","source":"sqlite","msg":"Error","sql":"UPDATE \"execution_entity\" SET \"status\"=? WHERE \"id\"=?","params":["failed","c1a2b3d4"],"errorCode":"SQLITE_BUSY","errorMessage":"database is locked"}

4. Common SQLite Error Codes in n8n & Fixes

SQLite Error Typical n8n Trigger Root Cause Quick Fix
SQLITE_BUSY Workflow execution stalls Database locked by another process Increase N8N_SQLITE_BUSY_TIMEOUT (default 5000 ms) or split heavy reads into separate transactions
SQLITE_CONSTRAINT Credential save fails Unique‑constraint violation (duplicate name) Ensure credential names are unique; use ON CONFLICT REPLACE only if intentional
SQLITE_FULL New execution cannot be inserted Disk quota exhausted or DB size limit reached Expand storage, prune old executions (n8n execution delete)
SQLITE_READONLY Write attempt in read‑only mode File‑system permissions changed after start Verify chmod 660 on database.sqlite and that the n8n user owns it
SQLITE_CORRUPT Random crashes Corrupted DB file (power loss, abrupt stop) Restore from backup; run sqlite3 database.sqlite "PRAGMA integrity_check;"

EEFA tip: From n8n v0.210 onward, you can set a per‑workflow timeout via Workflow Settings → Advanced → SQLite Busy Timeout, which overrides the global env var.


5. Step‑by‑Step Debugging Workflow

  1. Activate logging (see Section 2).
  2. Reproduce the failure – run the problematic node or trigger the webhook.
  3. Locate the offending query:
    grep -i '"msg":"Error"' /var/log/n8n/sqlite.log | tail -n 20
  4. Identify the error code (SQLITE_…).
  5. Cross‑reference with the table in Section 4 to understand the cause.
  6. Apply the corrective action (e.g., increase timeout, fix schema).
  7. Validate by re‑running the workflow and confirming the log no longer shows the error.
  8. Learn to Handle unsupported SQLite features, constraints, and version issues in n8n workflows.

5.1. Example: Fixing a SQLITE_BUSY During Bulk Inserts

# Observe repeated SQLITE_BUSY lines
grep SQLITE_BUSY /var/log/n8n/sqlite.log

**Log excerpt (compact)**

{"timestamp":"2025-12-24T15:01:12.045Z","level":"debug","source":"sqlite","msg":"Error","sql":"INSERT INTO \"execution_entity\" ...","errorCode":"SQLITE_BUSY","errorMessage":"database is locked"}

**Fix – increase busy timeout**

export N8N_SQLITE_BUSY_TIMEOUT=15000   # 15 seconds
systemctl restart n8n   # or docker restart n8n

Re‑run the workflow; the log now shows successful inserts with durationMs < 5 ms.


6. Log Rotation & Retention (Production‑Grade)

Configure built‑in rotation via environment variables (already shown) and complement it with a system‑wide logrotate policy.

# /etc/logrotate.d/n8n-sqlite
/var/log/n8n/sqlite.log* {
    daily
    rotate 14
    compress
    missingok
    notifempty
    create 0600 n8n n8n
    sharedscripts
    postrotate
        systemctl reload n8n > /dev/null 2>/dev/null || true
    endscript
}
# Test the configuration
logrotate -d /etc/logrotate.d/n8n-sqlite

EEFA caution: Do not compress logs while n8n is actively writing to them; the postrotate hook safely reloads the service after rotation.


7. Real‑Time Monitoring with tail & jq

For instant feedback while iterating on a workflow:

tail -f /var/log/n8n/sqlite.log | \
jq 'select(.msg=="Error") | {time:.timestamp, sql:.sql, code:.errorCode, msg:.errorMessage}'

This streams only error entries, showing timestamp, offending SQL, and the SQLite error code—ideal for a live debugging console.


8. Security Considerations

  • Mask sensitive data – set N8N_LOG_SENSITIVE_DATA=false to prevent credential values from appearing in params.
  • Restrict log file access
    chown n8n:n8n /var/log/n8n/sqlite.log*
    chmod 600 /var/log/n8n/sqlite.log*
  • Docker best practice – mount the log directory as a read‑only volume on the host side and let the container manage rotation internally.

10. Next Steps

  1. Implement logging on a staging environment first; verify that no credential values leak.
  2. Run a health‑check script that parses the last 24 h of logs for any SQLITE_ errors and alerts you via Slack.
  3. Explore sibling pages for targeted fixes (e.g., “n8n SQLite schema mismatch” or “n8n SQLite file‑permission errors”).

Conclusion

Enabling SQLite logging gives you a transparent view into the exact queries n8n executes, turning opaque “SQLITE_…” errors into actionable insights. Ensure smooth operation by addressing version conflicts, unsupported features, and constraint errors in n8n SQLite. By configuring environment‑driven logging, rotating logs responsibly, and filtering for errors with lightweight jq pipelines, you can quickly pinpoint lock contention, constraint violations, and other database issues without guessing. Apply the focused fixes from the error‑code table, and keep logging at debug level only when needed to maintain security and performance in production.

Leave a Comment

Your email address will not be published. Required fields are marked *