What's Actually Happening
HashiCorp Boundary fails to establish sessions to targets. Users cannot connect to infrastructure resources through Boundary.
The Error You'll See
Session failed:
```bash $ boundary connect -target-id ttcp_123456789
Error: error creating session: failed to authorize session ```
Worker unavailable:
Error: no workers available for targetConnection timeout:
Error: connection timed out: unable to establish sessionAuthentication error:
Error: error authenticating: permission deniedWhy This Happens
- 1.Worker issues - Boundary workers down or unreachable
- 2.Target misconfiguration - Invalid target address or port
- 3.Permission denied - User lacks access to target
- 4.Network connectivity - Workers cannot reach targets
- 5.Authentication expired - Token needs refresh
- 6.Host catalog issues - Host sets or catalogs misconfigured
Step 1: Check Boundary Status
```bash # Check Boundary server: boundary version
# Check controller status: boundary status
# List available scopes: boundary scopes list
# Check authentication: boundary authenticate password -login-name=admin
# Check current user: boundary users read -id <user-id>
# Check session limit: boundary config read ```
Step 2: Check Worker Status
```bash # List workers: boundary workers list
# Check worker status: boundary workers read -id <worker-id>
# Check worker is online: # Status should be "online"
# Check worker tags: boundary workers read -id <worker-id> -format=json | jq '.item.tags'
# Worker must have appropriate tags for target
# Check worker logs: journalctl -u boundary-worker -n 50
# For Kubernetes: kubectl logs -n boundary deployment/boundary-worker
# Restart worker if needed: systemctl restart boundary-worker ```
Step 3: Check Target Configuration
```bash # List targets: boundary targets list -scope-id <scope-id>
# Read target details: boundary targets read -id <target-id>
# Check target type: # - tcp (standard TCP) # - ssh # - rdp
# Check target address: boundary targets read -id <target-id> -format=json | jq '.item.attributes.value.destination'
# Should be valid IP or hostname
# Check default port: boundary targets read -id <target-id> -format=json | jq '.item.attributes.value.port'
# Update target if needed: boundary targets update tcp \ -id <target-id> \ -default-port 22 \ -default-host-catalog-id <catalog-id> \ -default-host-set-id <host-set-id> ```
Step 4: Check Host Catalog
```bash # List host catalogs: boundary host-catalogs list -scope-id <scope-id>
# Read host catalog: boundary host-catalogs read -id <catalog-id>
# List host sets: boundary host-sets list -host-catalog-id <catalog-id>
# Read host set: boundary host-sets read -id <host-set-id>
# Check hosts in set: boundary hosts list -host-set-id <host-set-id>
# For static host catalog: boundary hosts read -id <host-id>
# Verify host address: boundary hosts read -id <host-id> -format=json | jq '.item.attributes.value.address'
# Test connectivity from worker: ping <host-address> nc -zv <host-address> <port> ```
Step 5: Check Permissions
```bash # Check user roles: boundary roles list -scope-id <scope-id>
# Read user roles: boundary users read -id <user-id> -format=json | jq '.item.roles'
# Check role grants: boundary roles read -id <role-id>
# Required grants for session: # - type=target;id=<target-id>;actions=authorize-session
# Check group membership: boundary groups list -scope-id <scope-id>
# Add user to role: boundary roles add-principals \ -id <role-id> \ -principal <user-id>
# Create role with session grant: boundary roles create \ -scope-id <scope-id> \ -name "session-role" \ -grant "id=<target-id>;type=target;actions=authorize-session" ```
Step 6: Test Connectivity
```bash # Test worker to target connectivity:
# SSH into worker host: ssh boundary-worker-host
# Test target connectivity: nc -zv <target-address> <port>
# Check firewall: iptables -L -n | grep <port>
# Allow port: iptables -I INPUT -p tcp --dport <port> -j ACCEPT
# Check DNS: nslookup <target-hostname>
# Test from worker process: boundary-worker --test-connectivity <target-address>:<port>
# Check worker network configuration: ip route ip addr ```
Step 7: Check Authentication
```bash # Check auth methods: boundary auth-methods list -scope-id global
# Read auth method: boundary auth-methods read -id <auth-method-id>
# For password auth: boundary authenticate password \ -login-name <username> \ -password <password>
# For OIDC: boundary authenticate oidc \ -auth-method-id <auth-method-id>
# Check token validity: boundary scopes list -format=json | jq .
# If token expired, re-authenticate: boundary authenticate password -login-name <username>
# Check auth token TTL: boundary config read -format=json | jq '.item.auth_token_time_to_live' ```
Step 8: Check Session Logs
```bash # Check Boundary controller logs: journalctl -u boundary-controller -f
# Check for session errors: journalctl -u boundary-controller | grep -i "session|error|failed"
# Check worker logs: journalctl -u boundary-worker | grep -i "session|connection|error"
# Common errors: # - "worker not found" # - "target unreachable" # - "permission denied" # - "connection refused"
# Enable debug logging: # In controller config: log_level = "debug"
# Restart controller: systemctl restart boundary-controller ```
Step 9: Configure Worker Tags
```bash # Worker tags must match target worker filter:
# Check target worker filter: boundary targets read -id <target-id> -format=json | jq '.item.worker_filter'
# Example filter: # "type" in "/tags/environment"
# Add tags to worker: # In worker config: listener "tcp" { address = "0.0.0.0:9202" purpose = "proxy" }
worker { tags { type = ["aws", "production"] environment = ["prod"] } }
# Restart worker: systemctl restart boundary-worker
# Verify tags: boundary workers read -id <worker-id> -format=json | jq '.item.tags' ```
Step 10: Monitor Sessions
```bash # Create monitoring script: cat << 'EOF' > /usr/local/bin/monitor-boundary.sh #!/bin/bash
echo "=== Workers ===" boundary workers list -format=json | jq '.[] | {id: .id, status: .status}'
echo "" echo "=== Active Sessions ===" boundary sessions list -format=json | jq '.[] | {id: .id, status: .status, target_id: .target_id}'
echo "" echo "=== Recent Session Errors ===" journalctl -u boundary-controller --since "1 hour ago" | grep -i "session.*error|failed"
echo "" echo "=== Worker Connectivity ===" for worker in $(boundary workers list -format=json | jq -r '.[].id'); do echo "Worker $worker:" boundary workers read -id $worker -format=json | jq '{status: .status, last_status_change: .item.last_status_change}' done EOF
chmod +x /usr/local/bin/monitor-boundary.sh
# Prometheus metrics (if configured): curl http://localhost:9203/metrics | grep boundary
# Key metrics: # boundary_session_total # boundary_session_errors # boundary_worker_status
# Alerts: - alert: BoundaryWorkerOffline expr: boundary_worker_status == 0 for: 5m labels: severity: critical annotations: summary: "Boundary worker offline" ```
Boundary Session Failed Checklist
| Check | Command | Expected |
|---|---|---|
| Worker status | workers list | Online |
| Target config | targets read | Valid address |
| Host catalog | hosts list | Hosts exist |
| Permissions | roles read | Has authorize-session |
| Connectivity | nc -zv | Connected |
| Authentication | authenticate | Success |
Verify the Fix
```bash # After fixing session issue
# 1. Test authentication boundary authenticate password -login-name admin // Authentication successful
# 2. Check worker boundary workers list // Workers online
# 3. Test session boundary connect -target-id <target-id> // Session established
# 4. Verify connection # Connected to target via Boundary proxy
# 5. Check session status boundary sessions list // Session active
# 6. Monitor logs journalctl -u boundary-worker -f // No errors ```
Related Issues
- [Fix Vault Token Renewal Failed](/articles/fix-vault-token-renewal-failed)
- [Fix Keycloak User Login Failed](/articles/fix-keycloak-user-login-failed)
- [Fix Consul Agent Not Starting](/articles/fix-consul-agent-not-starting)