# Troubleshooting

This guide covers common issues and their solutions when running STA Connector with Elixir/Phoenix.

## Quick Diagnostics

### Health Check

```bash
# Phoenix application health
curl http://localhost:4000/api/v1/health

# Admin API health
curl -u admin:password http://localhost:4000/admin/health
```

### View Logs

```bash
# Docker
docker logs sta-connector -f

# Kubernetes
kubectl logs -f deployment/sta-connector -n sta-connector

# Local development
mix phx.server 2>&1 | tee phoenix.log

# IEx session
iex -S mix phx.server
```

### Check Metrics

```bash
curl -u admin:password http://localhost:4000/admin/metrics
```

---

## Startup Issues

### Configuration File Not Found

**Symptom:**
```
** (File.Error) could not read file "config/runtime.exs": no such file or directory
```

**Solution:**
1. Verify the config file exists:
   ```bash
   ls -la config/runtime.exs
   ```
2. Check environment variables are set:
   ```bash
   export DATABASE_URL="ecto://user:pass@localhost/sta_connector"
   export SECRET_KEY_BASE="your-64-char-secret-key"
   ```
3. Generate a secret key if needed:
   ```bash
   mix phx.gen.secret
   ```

### Invalid Configuration

**Symptom:**
```
** (RuntimeError) environment variable SECRET_KEY_BASE is missing.
```

**Solution:**
1. Set the required environment variable:
   ```bash
   export SECRET_KEY_BASE=$(mix phx.gen.secret)
   ```
2. For production releases:
   ```bash
   # In your .env file or deployment config
   SECRET_KEY_BASE=your-64-character-minimum-secret-key-here
   ```
3. Verify the key length (minimum 64 characters):
   ```elixir
   iex> String.length(System.get_env("SECRET_KEY_BASE"))
   64
   ```

### Port Already in Use (Port 4000)

**Symptom:**
```
** (ErlangError) Erlang error: :eaddrinuse
[error] Failed to start Ranch listener StaConnectorWeb.Endpoint.HTTP
```

**Solution:**
1. Find the process using port 4000:
   ```bash
   lsof -i :4000
   ```
2. Kill the process:
   ```bash
   kill -9 $(lsof -t -i:4000)
   ```
3. Or use a different port:
   ```elixir
   # config/runtime.exs
   config :sta_connector, StaConnectorWeb.Endpoint,
     http: [port: String.to_integer(System.get_env("PORT") || "4001")]
   ```

### Application Won't Start

**Symptom:**
```
** (Mix) Could not start application sta_connector: StaConnector.Application.start(:normal, []) returned an error
```

**Solution:**
1. Check all dependencies are compiled:
   ```bash
   mix deps.get
   mix deps.compile
   ```
2. Ensure database is running and accessible
3. Run migrations:
   ```bash
   mix ecto.create
   mix ecto.migrate
   ```
4. Check the full error in logs for specific module failures

---

## Database Issues (Ecto/PostgreSQL)

### Database Connection Failed

**Symptom:**
```
** (DBConnection.ConnectionError) tcp connect (localhost:5432): connection refused
```

**Solution:**
1. Verify PostgreSQL is running:
   ```bash
   # macOS
   brew services list | grep postgresql

   # Linux
   sudo systemctl status postgresql

   # Docker
   docker ps | grep postgres
   ```
2. Start PostgreSQL if not running:
   ```bash
   # macOS
   brew services start postgresql

   # Linux
   sudo systemctl start postgresql

   # Docker
   docker start postgres
   ```
3. Test connection:
   ```bash
   psql -h localhost -U postgres -d sta_connector
   ```

### Ecto Migration Failed

**Symptom:**
```
** (Postgrex.Error) ERROR 42P01 (undefined_table) relation "files" does not exist
```

**Solution:**
1. Run pending migrations:
   ```bash
   mix ecto.migrate
   ```
2. Check migration status:
   ```bash
   mix ecto.migrations
   ```
3. Reset database if needed (development only):
   ```bash
   mix ecto.reset
   ```
4. For production, run migrations manually:
   ```bash
   _build/prod/rel/sta_connector/bin/sta_connector eval "StaConnector.Release.migrate()"
   ```

### Migration Rollback Issues

**Symptom:**
```
** (Ecto.MigrationError) cannot reverse migration
```

**Solution:**
1. Write explicit down/0 functions in migrations:
   ```elixir
   def down do
     drop table(:files)
   end
   ```
2. Force rollback a specific version:
   ```bash
   mix ecto.rollback --step 1
   ```
3. Check migration file for irreversible operations

### Database Pool Exhausted

**Symptom:**
```
** (DBConnection.ConnectionError) connection not available and request was dropped from queue after 15000ms
```

**Solution:**
1. Increase pool size in config:
   ```elixir
   # config/runtime.exs
   config :sta_connector, StaConnector.Repo,
     pool_size: String.to_integer(System.get_env("POOL_SIZE") || "20")
   ```
2. Check for connection leaks (unclosed transactions)
3. Use `Ecto.Adapters.SQL.Sandbox` properly in tests
4. Monitor connections:
   ```sql
   SELECT count(*) FROM pg_stat_activity WHERE datname = 'sta_connector';
   ```

### PostgreSQL Authentication Failed

**Symptom:**
```
** (Postgrex.Error) FATAL 28P01 (invalid_password) password authentication failed for user "postgres"
```

**Solution:**
1. Verify DATABASE_URL is correct:
   ```bash
   echo $DATABASE_URL
   # Should be: ecto://username:password@hostname/database_name
   ```
2. Check PostgreSQL pg_hba.conf for authentication method
3. Reset password if needed:
   ```sql
   ALTER USER postgres PASSWORD 'new_password';
   ```

---

## Phoenix Channels / WebSocket Issues

### WebSocket Connection Failed

**Symptom:**
```
WebSocket connection to 'ws://localhost:4000/socket/websocket' failed
```

**Solution:**
1. Verify endpoint configuration:
   ```elixir
   # lib/sta_connector_web/endpoint.ex
   socket "/socket", StaConnectorWeb.UserSocket,
     websocket: true,
     longpoll: false
   ```
2. Check CORS settings for cross-origin connections:
   ```elixir
   # config/config.exs
   config :sta_connector, StaConnectorWeb.Endpoint,
     check_origin: ["//localhost:3000", "//yourdomain.com"]
   ```
3. For development, disable origin check:
   ```elixir
   check_origin: false
   ```

### Channel Join Failed

**Symptom:**
```elixir
{:error, %{reason: "unauthorized"}}
```

**Solution:**
1. Check socket authentication:
   ```elixir
   # lib/sta_connector_web/user_socket.ex
   def connect(%{"token" => token}, socket, _connect_info) do
     case verify_token(token) do
       {:ok, user_id} -> {:ok, assign(socket, :user_id, user_id)}
       {:error, _} -> :error
     end
   end
   ```
2. Verify the token is being sent from the client
3. Check channel authorization in join/3:
   ```elixir
   def join("room:" <> room_id, _params, socket) do
     if authorized?(socket.assigns.user_id, room_id) do
       {:ok, socket}
     else
       {:error, %{reason: "unauthorized"}}
     end
   end
   ```

### Channel Timeout

**Symptom:**
```
Channel process terminated: timeout
```

**Solution:**
1. Increase timeout in channel:
   ```elixir
   use Phoenix.Channel
   @impl true
   def join(topic, payload, socket) do
     send(self(), :after_join)
     {:ok, socket}
   end
   ```
2. Handle long operations asynchronously:
   ```elixir
   def handle_in("heavy_operation", payload, socket) do
     Task.start(fn -> perform_heavy_operation(payload) end)
     {:noreply, socket}
   end
   ```
3. Configure socket timeout:
   ```elixir
   socket "/socket", StaConnectorWeb.UserSocket,
     websocket: [timeout: 60_000]
   ```

### PubSub Issues

**Symptom:**
```
** (ArgumentError) no pubsub configured for StaConnectorWeb.Endpoint
```

**Solution:**
1. Configure PubSub in endpoint:
   ```elixir
   # config/config.exs
   config :sta_connector, StaConnectorWeb.Endpoint,
     pubsub_server: StaConnector.PubSub
   ```
2. Start PubSub in application supervisor:
   ```elixir
   # lib/sta_connector/application.ex
   children = [
     {Phoenix.PubSub, name: StaConnector.PubSub},
     # ... other children
   ]
   ```

---

## Debugging Tools

### Using Logger

**Basic Logging:**
```elixir
require Logger

Logger.debug("Processing file: #{file.name}")
Logger.info("File uploaded successfully")
Logger.warning("Rate limit approaching: #{remaining} requests left")
Logger.error("Failed to connect to STA: #{inspect(reason)}")
```

**Configure Log Level:**
```elixir
# config/runtime.exs
config :logger, level: :debug

# Or at runtime in IEx
Logger.configure(level: :debug)
```

**Log to File:**
```elixir
# config/config.exs
config :logger,
  backends: [:console, {LoggerFileBackend, :file_log}]

config :logger, :file_log,
  path: "/var/log/sta_connector/app.log",
  level: :info
```

### Using :observer

**Start Observer:**
```elixir
# In IEx session
:observer.start()
```

**Observer Features:**
- **System Tab**: Memory usage, CPU load, uptime
- **Load Charts**: Real-time CPU and memory graphs
- **Applications Tab**: Supervision trees, process hierarchy
- **Processes Tab**: All running processes, message queues
- **Table Viewer**: ETS tables, Mnesia tables

**Remote Observer:**
```bash
# On the server
iex --name sta_connector@server --cookie secret -S mix phx.server

# On your local machine
iex --name observer@local --cookie secret
:observer.start()
# Then connect to sta_connector@server from observer
```

### Using :sys.get_state()

**Inspect GenServer State:**
```elixir
# Get state of a named GenServer
:sys.get_state(StaConnector.FileProcessor)

# Get state by PID
pid = Process.whereis(StaConnector.FileProcessor)
:sys.get_state(pid)
```

**Trace GenServer Calls:**
```elixir
# Enable tracing
:sys.trace(StaConnector.FileProcessor, true)

# Make calls to the GenServer - you'll see trace output
StaConnector.FileProcessor.process_file(file)

# Disable tracing
:sys.trace(StaConnector.FileProcessor, false)
```

**Get Process Statistics:**
```elixir
:sys.statistics(StaConnector.FileProcessor, :get)
# Returns: {:ok, stats}
```

### Using IEx Helpers

**Inspect Running Processes:**
```elixir
# List all processes
Process.list()

# Get process info
Process.info(pid)

# Find processes by name
Process.whereis(StaConnector.Repo)

# Check supervisor children
Supervisor.which_children(StaConnector.Supervisor)
```

**Debug Specific Module:**
```elixir
# Recompile module with debug info
r StaConnector.FileProcessor

# Get module info
StaConnector.FileProcessor.__info__(:functions)
```

### Using :dbg (OTP 25+)

**Trace Function Calls:**
```elixir
# Trace all calls to a module
:dbg.tracer()
:dbg.p(:all, :c)
:dbg.tp(StaConnector.StaClient, :_, [])

# Make calls and see traces
StaConnector.StaClient.list_files("CCS")

# Stop tracing
:dbg.stop()
```

---

## STA Connection Issues

### Authentication Failed

**Symptom:**
```
** (StaConnector.StaError) STA authentication failed: invalid credentials
```

**Solution:**
1. Verify Sisbacen credentials are correct
2. Check for typos in username/password
3. Ensure no special characters need escaping
4. Test credentials with BCB directly

### Connection Timeout

**Symptom:**
```
** (HTTPoison.Error) :timeout
```

**Solution:**
1. Check network connectivity:
   ```bash
   curl -I https://sta-h.bcb.gov.br/staws
   ```
2. Verify firewall allows HTTPS outbound
3. Increase timeout in HTTP client:
   ```elixir
   HTTPoison.get(url, headers, timeout: 60_000, recv_timeout: 60_000)
   ```
4. Check BCB status page for outages

### Rate Limited

**Symptom:**
```
** (StaConnector.RateLimitError) STA rate limit exceeded (429)
```

**Solution:**
1. Reduce polling frequency in config
2. Wait for rate limit window to reset (1 minute)
3. Implement exponential backoff
4. Monitor rate limit in metrics

---

## Performance Issues

### High Memory Usage

**Symptom:** BEAM memory keeps growing.

**Solution:**
1. Check for process leaks:
   ```elixir
   :erlang.system_info(:process_count)
   ```
2. Inspect large processes:
   ```elixir
   Process.list()
   |> Enum.map(fn pid -> {pid, Process.info(pid, :memory)} end)
   |> Enum.sort_by(fn {_, {:memory, mem}} -> mem end, :desc)
   |> Enum.take(10)
   ```
3. Check ETS table sizes:
   ```elixir
   :ets.all()
   |> Enum.map(fn tab -> {tab, :ets.info(tab, :memory)} end)
   |> Enum.sort_by(&elem(&1, 1), :desc)
   ```
4. Force garbage collection:
   ```elixir
   :erlang.garbage_collect()
   ```

### Slow Response Times

**Symptom:** API responses take several seconds.

**Solution:**
1. Profile with :fprof:
   ```elixir
   :fprof.apply(&slow_function/0, [])
   :fprof.profile()
   :fprof.analyse()
   ```
2. Check database query times:
   ```elixir
   # config/config.exs
   config :sta_connector, StaConnector.Repo,
     log: :debug
   ```
3. Use EXPLAIN ANALYZE for slow queries:
   ```elixir
   Ecto.Adapters.SQL.explain(StaConnector.Repo, :all, query)
   ```

---

## Docker Issues

### Container Keeps Restarting

**Symptom:** Container restarts repeatedly.

**Solution:**
1. Check logs for error:
   ```bash
   docker logs sta-connector
   ```
2. Verify environment variables:
   ```bash
   docker exec sta-connector env | grep -E "(DATABASE_URL|SECRET_KEY_BASE)"
   ```
3. Check health check configuration:
   ```yaml
   healthcheck:
     test: ["CMD", "curl", "-f", "http://localhost:4000/api/v1/health"]
     start_period: 30s
   ```

### Release Won't Start

**Symptom:**
```
ERROR! Config provider Config.Reader failed with: ** (File.Error) could not read file
```

**Solution:**
1. Ensure runtime.exs is included in release:
   ```elixir
   # mix.exs
   def project do
     [
       releases: [
         sta_connector: [
           config_providers: [{Config.Reader, {:system, "RELEASE_ROOT", "/config/runtime.exs"}}]
         ]
       ]
     ]
   end
   ```
2. Mount config file in Docker:
   ```yaml
   volumes:
     - ./config/runtime.exs:/app/config/runtime.exs:ro
   ```

---

## Getting Help

If you can't resolve an issue:

1. **Check existing issues** on GitHub
2. **Search documentation** for similar problems
3. **Enable debug logging** and collect logs:
   ```elixir
   Logger.configure(level: :debug)
   ```
4. **Open a new issue** with:
   - Elixir/OTP version: `elixir --version`
   - Phoenix version: `mix deps | grep phoenix`
   - Full error message and stacktrace
   - Steps to reproduce
   - Relevant configuration (redact secrets)

---

## Next Steps

- [Configuration](/guide/configuration) - Configuration reference
- [Admin API](/api/admin) - API for management
- [Kubernetes Deployment](/en/deployment/kubernetes) - Kubernetes setup
