# How to Troubleshoot Common Issues in TaxHacker: Complete Diagnostics Guide

> Troubleshoot common TaxHacker issues with this diagnostics guide. Resolve problems in file uploads, AI extraction, authentication, payments, and exports to keep your tax processing smooth.

- Repository: [Vasily Zubarev/TaxHacker](https://github.com/vas3k/TaxHacker)
- Tags: how-to-guide
- Published: 2026-04-01

---

**Most TaxHacker runtime errors originate in five subsystems: file uploads and storage, AI extraction services, Better-Auth configuration, Stripe payment processing, or export and backup operations.**

TaxHacker is a self-hosted AI-powered accounting application built with Next.js 15+, Prisma, and dedicated microservices for document processing and payments. When you need to troubleshoot common issues in TaxHacker, understanding the specific file paths and validation logic in its codebase allows you to pinpoint failures quickly without extensive debugging.

## File Uploads and Storage Issues

File handling represents the most frequent source of runtime errors in TaxHacker. The upload flow begins at `app/(app)/unsorted/actions.ts`, which delegates path computations and storage validation to [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts).

### Path Traversal Protection

The `safePathJoin` function in [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts) (lines 56-57) aggressively validates paths to prevent directory traversal attacks. If you encounter a **"Path traversal detected"** error, the filename contains `../` sequences or other dangerous characters attempting to escape the user upload directory.

```typescript
// Verify safePathJoin behavior
import { safePathJoin } from '@/lib/files'

const userPath = '/uploads/user@example.com'
console.log(safePathJoin(userPath, '../evil.txt')) // throws "Path traversal detected"

```

Sanitize client-side filenames before transmission by stripping path components:

```typescript
function cleanFilename(name: string): string {
  return name.replace(/\.\.+/g, '').replace(/[<>:"/\\|?*]/g, '_')
}

```

### Storage Quota Violations

The **"Insufficient storage"** error triggers when `isEnoughStorageToUploadFile` (lines 88-93 in [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts)) detects the user has exceeded their limit. Verify current usage against the database quota:

```typescript
import { getDirectorySize, getUserUploadsDirectory } from '@/lib/files'
import { prisma } from '@/prisma/client'

async function checkUserQuota(userId: number) {
  const user = await prisma.users.findUnique({ where: { id: userId } })
  const dir = getUserUploadsDirectory(user)
  const used = await getDirectorySize(dir)
  console.log('Used:', used, 'Limit:', user.storageLimit)
}

```

To increase a user's storage limit via Prisma:

```typescript
await prisma.users.update({
  where: { id: userId },
  data: { storageLimit: 10 * 1024 * 1024 * 1024 } // 10 GB
})

```

### Missing File on Disk Errors

If uploads fail with **"File not found on disk"** errors, check lines 97-98 in `app/(app)/unsorted/actions.ts`. This usually indicates an interrupted write or desynchronization between the database record and the physical file in the `UPLOAD_PATH` directory. The error can also originate from [`ai/attachments.ts`](https://github.com/vas3k/TaxHacker/blob/main/ai/attachments.ts) (line 18) when the preview generator expects files that were never saved to the `unsorted/` or `previews/` subdirectories.

## AI Extraction and Analysis Failures

TaxHacker's document analysis relies on providers configured in [`lib/llm-providers.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/llm-providers.ts) and orchestrated through [`ai/analyze.ts`](https://github.com/vas3k/TaxHacker/blob/main/ai/analyze.ts).

### Provider Authentication Errors

The **"Failed to analyze invoice"** error typically originates from lines 32-33 in [`ai/analyze.ts`](https://github.com/vas3k/TaxHacker/blob/main/ai/analyze.ts), where the code throws when a provider returns an error payload. Verify your API keys are loaded correctly in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts):

```typescript
import config from '@/lib/config'

console.log('OpenAI key:', config.ai.openaiApiKey?.slice(0, 4))
if (!config.ai.openaiApiKey) {
  throw new Error('OPENAI_API_KEY is missing – set it in .env')
}

```

Required environment variables include `OPENAI_API_KEY`, `GOOGLE_API_KEY`, or `MISTRAL_API_KEY` as defined in the configuration schema.

### Currency Formatting Edge Cases

The `formatCurrency` utility in [`lib/utils.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/utils.ts) (lines 21-24) falls back to plain strings when `Intl.NumberFormat` throws for unsupported currency codes. If you see **"Unsupported currency"** warnings in logs, the invoice likely contains an obscure cryptocurrency or invalid ISO code that cannot be processed by the standard formatting library.

## Authentication and Self-Hosted Mode Errors

TaxHacker uses Better-Auth for authentication, configured in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts) with environment variables validated in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts).

### Secret Validation Failures

The `BETTER_AUTH_SECRET` must be at least 16 characters long. Lines 13-16 in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts) enforce this minimum length during application startup. If authentication fails with cryptic errors, verify your secret meets the requirement:

```typescript
import config from '@/lib/config'

if (!config.auth.secret || config.auth.secret.length < 16) {
  console.error('Auth secret must be ≥16 characters – check BETTER_AUTH_SECRET')
}

```

### User Not Found Errors

The error **"User with this email does not exist"** maps directly to lines 58-59 in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts), where the system raises `APIError("NOT_FOUND")` for unknown login attempts.

### Unexpected Signup Disabling

In self-hosted mode, signup disables automatically when `SELF_HOSTED_MODE=true` or `DISABLE_SIGNUP=true`. Check lines 64-66 in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts) to understand the boolean logic affecting `auth.disableSignup`. If you see **"Signup disabled unexpectedly"**, verify these environment variables are set according to your deployment intentions.

## Stripe Integration Failures

Payment processing errors typically surface in [`app/api/stripe/checkout/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/checkout/route.ts) or the webhook handler at [`app/api/stripe/webhook/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/webhook/route.ts).

### Checkout Session Failures

Lines 42-48 in the checkout route catch Stripe SDK exceptions and return JSON error responses. The **"Failed to create Stripe checkout session"** message indicates missing or invalid `STRIPE_SECRET_KEY` configuration.

Verify your keys are loaded:

```typescript
import config from '@/lib/config'
console.log('Stripe secret:', config.stripe.secretKey?.slice(0, 4))

```

### Webhook Plan Mapping Errors

The webhook handler (lines 82-83) throws **"Plan not found for price ID"** when Stripe sends a price ID not present in the local plan configuration. Ensure your production price IDs match the environment variables in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts). For **"Invalid webhook signature"** errors, verify the `STRIPE_WEBHOOK_SECRET` environment variable matches your Stripe dashboard configuration.

## Export and Backup Malfunctions

Data export and backup functionality relies on file system writes to temporary directories.

### ZIP Creation Failures

The **"Failed to create zip folder"** error at line 96 in `app/(app)/export/transactions/route.ts` and line 54 in `app/(app)/settings/backups/data/route.ts` indicates permission problems with `os.tmpdir()` or the `UPLOAD_PATH` directory.

Check your temporary directory permissions:

```typescript
import os from 'os'
console.log('Tmp dir:', os.tmpdir())

```

If running in Docker, ensure the container user has write access or override the path:

```bash

# In docker-compose.yml

environment:
  - TMPDIR=/app/tmp
volumes:
  - ./tmp:/app/tmp

```

## General Error Debugging Techniques

TaxHacker centralizes error handling in [`lib/utils.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/utils.ts). The `fetchAsBase64` function (lines 84-85 and 95-98) demonstrates the standard pattern: network errors throw with **"Error fetching image as data URL"**, which appears in server logs when preview generation fails for remote images or when network connectivity is interrupted.

Enable verbose logging by inspecting caught errors in API routes:

```typescript
try {
  await someAsyncOperation()
} catch (e) {
  console.error('Unexpected error:', e)
  return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
}

```

Always ensure your deployment captures `stdout` and `stderr` via Docker logs or systemd journal to view these diagnostic messages.

## Summary

- **File upload errors** usually indicate path traversal attempts blocked by `safePathJoin` (lines 56-57) in [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts) or quota violations detected by `isEnoughStorageToUploadFile` (lines 88-93).
- **AI extraction failures** require verifying `OPENAI_API_KEY`, `GOOGLE_API_KEY`, or `MISTRAL_API_KEY` in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts) and checking provider response handling in [`ai/analyze.ts`](https://github.com/vas3k/TaxHacker/blob/main/ai/analyze.ts) (lines 32-33).
- **Authentication issues** stem from short `BETTER_AUTH_SECRET` values (minimum 16 characters, lines 13-16 in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts)) or self-hosted mode configuration affecting signup in [`lib/auth.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/auth.ts) (lines 58-59).
- **Stripe errors** map to missing price IDs in [`app/api/stripe/webhook/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/webhook/route.ts) (lines 82-83) or invalid checkout session configurations in [`app/api/stripe/checkout/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/checkout/route.ts) (lines 42-48).
- **Export and backup failures** indicate `os.tmpdir()` permission problems or missing write access to the `UPLOAD_PATH` directory at `app/(app)/export/transactions/route.ts` (line 96).

## Frequently Asked Questions

### Why does TaxHacker show "Path traversal detected" when uploading documents?

This security error originates in [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts) lines 56-57 where `safePathJoin` detects `../` patterns attempting to escape the user upload directory. Clean filenames on the client by removing path separators and special characters before transmission, or check that the `UPLOAD_PATH` environment variable points to a valid, writable directory.

### How do I fix "Failed to analyze invoice" errors during AI processing?

First verify your provider API keys are loaded in [`lib/config.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/config.ts) and meet the requirements for `OPENAI_API_KEY`, `GOOGLE_API_KEY`, or `MISTRAL_API_KEY`. Then check server logs for the specific error message thrown at lines 32-33 in [`ai/analyze.ts`](https://github.com/vas3k/TaxHacker/blob/main/ai/analyze.ts), which contains the provider's detailed rejection reason such as quota limits or invalid authentication.

### What causes "Insufficient storage" errors in self-hosted deployments?

The `isEnoughStorageToUploadFile` function in [`lib/files.ts`](https://github.com/vas3k/TaxHacker/blob/main/lib/files.ts) (lines 88-93) compares `user.storageUsed` plus the incoming file size against `user.storageLimit`. Run `getDirectorySize` on the user's upload folder to verify actual disk usage, then update the `storageLimit` column in the Prisma `users` table if the user has legitimately exceeded their quota.

### Why are Stripe webhooks failing with "Plan not found for price ID"?

The webhook handler in [`app/api/stripe/webhook/route.ts`](https://github.com/vas3k/TaxHacker/blob/main/app/api/stripe/webhook/route.ts) (lines 82-83) cannot map the Stripe `price.id` to a local plan configuration. Ensure your environment variables contain the correct price IDs for your production Stripe products, and verify the `STRIPE_WEBHOOK_SECRET` matches your Stripe dashboard configuration to prevent signature validation failures.