Zitare was opaque Latin/Italian-flavored branding. Renamed to clear English "quotes" (DE: Zitate) matching short-concrete-noun cluster. - Module, routes, API, i18n, standalone landing app, plans dirs - Dexie tables: quotesFavorites, quotesLists, quotesListTags, customQuotes (dropped redundant "quotes" prefix on the last) - Logo QuotesLogo, theme quotes.css, search provider, dashboard widget QuoteWidget - German user-facing label "Zitate" (English brand stays Quotes) Pre-launch, no data migration needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
Troubleshooting Guide
Common issues and solutions for the mana-monorepo.
Table of Contents
- Recursive Turbo Calls
- Build Issues
- Linting Issues
- NestJS Dependency Injection
- Staging Deployment Issues
- GitHub Running Disabled Workflows
- chat-backend Container Unhealthy
- SvelteKit Static Environment Variable Imports
- Orphan Docker Containers
- Client-Side Calling localhost Instead of Public IP
- CORS Blocking Cross-Origin Requests
- Missing Database Schema
- pnpm Symlinks Broken in Docker Container
- Hardcoded localhost URLs in SvelteKit Web Apps
Recursive Turbo Calls
Problem: Infinite Loop / Tasks Running Forever
Symptoms:
pnpm run buildruns for 10+ minutes without completingpnpm run linthangs indefinitelypnpm run type-checkshows thousands of duplicate task entries- CI/CD pipelines timeout after 10+ minutes
Root Cause:
Parent workspace packages (e.g., apps/quotes/package.json, apps/presi/package.json) have scripts that call turbo run <task>, creating an infinite recursion loop.
How It Happens
Root turbo → finds "build" script in apps/quotes/package.json
→ runs "turbo run build" in quotes
→ finds "build" script again
→ runs "turbo run build" again
→ (infinite loop!)
❌ WRONG - Causes Infinite Recursion
// apps/quotes/package.json - DON'T DO THIS!
{
"scripts": {
"build": "turbo run build", // ❌ WRONG
"lint": "turbo run lint", // ❌ WRONG
"type-check": "turbo run type-check", // ❌ WRONG
"clean": "turbo run clean" // ❌ WRONG
}
}
// apps/picture/package.json - DON'T DO THIS!
{
"scripts": {
"build": "pnpm run --recursive build", // ❌ WRONG
"lint": "pnpm --filter '@picture/*' run lint" // ❌ WRONG
}
}
✅ CORRECT - Let Root Turbo Handle Orchestration
// apps/quotes/package.json - CORRECT
{
"scripts": {
"dev": "turbo run dev", // ✅ OK for dev (persistent task, scoped)
// No build, lint, type-check scripts - handled by root turbo
"db:push": "pnpm --filter @quotes/backend db:push", // ✅ OK
"db:studio": "pnpm --filter @quotes/backend db:studio" // ✅ OK
}
}
Why dev is the Exception
Using turbo run dev in parent packages is acceptable because:
- It's typically run directly on that package (scoped:
pnpm quotes:dev) - Dev tasks are persistent (long-running) and turbo handles them differently
- Root never orchestrates
devacross all packages simultaneously
The Rule
Parent workspace packages must NEVER have scripts that call
turbo run <task>for tasks that turbo orchestrates from the root.
Tasks orchestrated from root (defined in turbo.json):
- ✅
build- Root handles this - ✅
lint- Root handles this - ✅
type-check- Root handles this - ✅
test- Root handles this - ✅
clean- Root handles this - ❌
dev- Exception (scoped usage is fine)
How to Fix
If you added a recursive script:
- Open the parent package.json (e.g.,
apps/myapp/package.json) - Remove the problematic script entirely:
{
"scripts": {
"dev": "turbo run dev",
- "build": "turbo run build",
- "lint": "turbo run lint",
- "type-check": "turbo run type-check",
"db:push": "pnpm --filter @myapp/backend db:push"
}
}
- The root
turbo.jsonalready handles orchestration for these tasks
Affected Locations
Parent packages are located at:
apps/*/package.json(e.g.,apps/quotes/package.json)games/*/package.json(e.g.,games/mana-games/package.json)
Do NOT add turbo scripts here!
Child packages (these are fine):
apps/*/apps/*/package.json(e.g.,apps/quotes/apps/backend/package.json)packages/*/package.json(e.g.,packages/shared-theme/package.json)
Build Issues
Build Fails with "ELIFECYCLE Command failed"
Check for:
- Recursive turbo calls (see above)
- Missing dependencies in a package
- TypeScript errors in source code
- Import/export mismatches
Debugging:
# Run build and capture full output
pnpm run build 2>&1 | tee build.log
# Search for actual error (not just ELIFECYCLE)
grep -A10 "error during build" build.log
# Build specific package to isolate issue
pnpm --filter @quotes/backend build
Build Times Out in CI
Symptoms:
- CI runs for 10+ minutes
- Timeout before completion
- "No output has been received in the last 10m0s"
Solution:
This is almost always caused by recursive turbo calls. See the Recursive Turbo Calls section above.
Quick fix:
# Locally, check if build completes in reasonable time
time pnpm run build
# Should complete in < 2 minutes for clean build
# Should complete in < 30 seconds for cached build
If it takes longer than 2-3 minutes, you have recursive scripts.
Linting Issues
Lint Hangs or Runs Forever
Same issue as build - recursive turbo calls!
❌ WRONG:
// apps/presi/package.json - DON'T DO THIS!
{
"scripts": {
"lint": "pnpm --filter '@presi/*' run lint" // ❌ Recursive
}
}
✅ CORRECT:
// apps/presi/package.json - Remove the lint script
{
"scripts": {
"dev": "pnpm --filter '@presi/*' run dev"
// No lint script - root turbo handles it
}
}
Run lint from root:
# Lint all packages
pnpm run lint
# Lint specific package
pnpm --filter @presi/backend lint
# Lint specific project
pnpm turbo run lint --filter=presi
ESLint Errors
Common issues:
-
Missing eslint config
# Add shared config pnpm add -D @mana/eslint-config --filter @myapp/backend -
Incompatible ESLint versions
# Check versions pnpm ls eslint # Update to match root version pnpm add -D eslint@latest --filter @myapp/backend
Prevention Checklist
When creating a new app or package:
- DO NOT add
build,lint,type-check, ortestscripts to parent packages - DO add these scripts to child packages (apps/myapp/apps/backend/package.json)
- DO use project-specific scripts (e.g.,
db:push,db:studio) - DO test locally:
pnpm run buildshould complete in < 2 minutes - DO refer to
CLAUDE.mdfor patterns
Quick Validation
# Check for problematic patterns in parent packages
for pkg in apps/*/package.json games/*/package.json; do
if grep -q '"build".*turbo run build' "$pkg" 2>/dev/null; then
echo "❌ RECURSIVE SCRIPT FOUND: $pkg"
fi
done
NestJS Dependency Injection
Problem: "Nest can't resolve dependencies" Error
Symptoms:
- NestJS fails to start with error:
Nest can't resolve dependencies of the XService (?) - Error mentions "argument Function at index [0] is available"
- The module imports look correct but service still won't inject
Root Cause:
Using type-only imports (import {X }) for classes that need to be injected. TypeScript erases type-only imports at compile time, so the actual class is not available at runtime for dependency injection.
❌ WRONG - Type-Only Import
// services/mana-auth/src/ai/ai.service.ts - DON'T DO THIS!
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; // ❌ Type-only import
@Injectable()
export class AiService {
constructor(private configService: ConfigService) {
// NestJS can't inject ConfigService because it was type-only imported!
}
}
What happens:
- TypeScript compiles the code
- The
typekeyword tells TypeScript to erase the import at compile time - The compiled JS has NO import for ConfigService
- At runtime, NestJS can't find the ConfigService class to inject
- Error: "Nest can't resolve dependencies of the AiService (?)"
✅ CORRECT - Regular Import
// services/mana-auth/src/ai/ai.service.ts - CORRECT
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config'; // ✅ Regular import
@Injectable()
export class AiService {
constructor(private configService: ConfigService) {
// ConfigService is properly imported and can be injected
}
}
The Rule
For NestJS dependency injection, NEVER use type-only imports (
import {X }) for classes you need to inject.
- ✅
import { ConfigService }- Regular import (works) - ❌
import {ConfigService }- Type-only import (breaks DI) - ✅
import type { MyInterface }- Type-only for interfaces (fine, not injected) - ✅
import {MyType, MyClass }- Mixed (MyType erased, MyClass available)
How to Fix
- Find the service with the DI error
- Check all imports for classes used in the constructor
- Remove the
typekeyword from class imports:
import { Injectable } from '@nestjs/common';
- import {ConfigService } from '@nestjs/config';
+ import { ConfigService } from '@nestjs/config';
@Injectable()
export class AiService {
constructor(private configService: ConfigService) {}
}
- Rebuild and test:
pnpm --filter mana-auth build
pnpm --filter mana-auth start:dev
Debugging
If you're still getting DI errors after removing type-only imports:
- Check the module imports the provider's dependencies:
@Module({
imports: [ConfigModule], // ← ConfigService needs ConfigModule
providers: [AiService],
exports: [AiService],
})
export class AiModule {}
- Verify the compiled JavaScript:
# Build the service
pnpm --filter mana-auth build
# Check the compiled output
cat services/mana-auth/dist/ai/ai.service.js | grep "require"
# Should see:
# const config_1 = require("@nestjs/config"); ✅ Good
# NOT:
# const config_1 = undefined; ❌ Bad (type-only import)
- Check Docker builds:
If the error only happens in Docker but not locally:
# Build Docker image without cache
docker build --no-cache -f services/mana-auth/Dockerfile -t test .
# Check the compiled code in the image
docker run --rm --entrypoint cat test /app/dist/ai/ai.service.js
Related Issues
- Commit d69cc607 - Fixed type-only ConfigService import in AiService
- TypeScript
import typevsimport {}- both erase at compile time - Docker layer caching can hide fixes if source wasn't properly copied
References
- CLAUDE.md - Turborepo Configuration
- turbo.json - Root task orchestration
- Turborepo Docs
Getting Help
If you encounter an issue not covered here:
- Check the GitHub Issues
- Review recent commits that may have introduced the issue
- Run
pnpm cleanandpnpm installto reset - Create a new issue with full error logs