Skip to main content

Troubleshooting Common Issues

This guide helps you diagnose and fix common issues when deploying and running applications on the Strongly platform.

Build Failures​

Slow Builds​

Problem: A build takes a long time. Builds have no time limit: the build keeps running until it succeeds or fails, or until you cancel it.

Symptoms:

  • Build stays in building for a long time
  • Large dependencies downloading
  • Complex build steps

Solutions:

  1. Optimize Docker build:
# Use .dockerignore to exclude unnecessary files
node_modules
.git
*.log

# Use multi-stage builds
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM node:18-alpine
COPY --from=builder /app/dist ./dist
  1. Leverage layer caching:
# Copy package files first (changes less often)
COPY package*.json ./
RUN npm ci

# Copy code last (changes more often)
COPY . .
  1. Reduce dependencies:
// Remove unnecessary devDependencies
{
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {}
}

Build Status Flow​

Builds progress through these statuses:

pending -> building -> completed (success)
-> failed (build error)
-> cancelled (user cancelled)

Cannot connect to app builder service​

Problem: The platform could not take the deploy

Symptoms:

  • Error: Cannot connect to app builder service
  • Deployment fails before the build starts

Solutions:

  1. Retry deployment: Wait a moment and deploy again
  2. Contact your administrator if it keeps happening

Dockerfile Syntax Errors​

Problem: Invalid Dockerfile syntax

Symptoms:

  • Build fails immediately
  • Error: "Dockerfile parse error"

Common Issues:

# Bad: Missing WORKDIR
COPY . .

# Good: Set WORKDIR first
WORKDIR /app
COPY . .

# Bad: Wrong order (FROM must be first)
RUN apt-get update
FROM node:18

# Good: FROM first
FROM node:18
RUN apt-get update

# Bad: Missing quotes for paths with spaces
COPY my folder /app

# Good: Quote paths
COPY "my folder" /app

Solution: Validate Dockerfile locally before deploying:

docker build -t test .

Missing Files in Build Context​

Problem: Files not found during build

Symptoms:

  • COPY command fails
  • Module not found errors

Solutions:

  1. Check archive structure:
# The manifest (and your Dockerfile, if you ship one) must be in the root
app.tar.gz
├── Dockerfile
├── strongly.manifest.yaml
├── package.json
└── src/
  1. Verify .dockerignore isn't excluding needed files:
# Don't ignore required files
!package.json
!src/
  1. Use correct COPY paths:
# Relative to build context root
COPY package.json ./
COPY src/ ./src/

Stale Builds​

Problem: Old builds lingering in pending or building state

Solutions:

  1. Check if the build is still actively running
  2. Builds stuck for more than twice the timeout are automatically marked failed; you can also trigger this cleanup via the REST API (POST /builds/cleanup/stale)
  3. Create a new deployment which will start a fresh build

Application Startup Issues​

Health Check Failures​

Problem: App deployed but health checks fail

Symptoms:

  • Status shows "Unhealthy"
  • The app keeps restarting
  • The status bar's reason mentions "CrashLoopBackOff"

Solutions:

  1. Implement health check endpoint:
// Express.js
app.get('/health', (req, res) => {
res.status(200).json({ status: 'ok' });
});
  1. Verify health check path in manifest:
health_check:
path: /health # Must match your endpoint
port: 3000
initial_delay: 15 # Give app time to start
  1. Increase startup timeout (in manifest runtime section):
runtime:
startup_timeout: 120 # Give more time for slow-starting apps
  1. Check application logs:
Navigate to app details -> Logs tab
Look for startup errors
  1. Test locally:
docker run -p 3000:3000 my-app
curl http://localhost:3000/health

Port Binding Errors​

Problem: Application fails to start due to port conflicts

Symptoms:

  • "Port already in use"
  • "EADDRINUSE" error
  • App crashes on startup

Solutions:

  1. Listen on the port your manifest declares: the platform routes to that port, and sets the PORT environment variable to it, so binding PORT or the declared port both work. "Port already in use" means something else in the container already holds that port.
// server.js
const PORT = process.env.PORT || 3000;
app.listen(PORT);
# manifest - the port the app listens on (PORT is set to it)
ports:
- port: 3000
expose: true
  1. Use PORT environment variable:
// Always use environment variable
const PORT = process.env.PORT;
if (!PORT) {
throw new Error('PORT environment variable not set');
}

Missing Environment Variables​

Problem: App crashes due to missing configuration

Symptoms:

  • "Environment variable not defined"
  • "Cannot read property of undefined"
  • Database connection errors

Solutions:

  1. Check STRONGLY_SERVICES is parsed correctly:
const data = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
const services = data.services || {};

// Check addons
const mongoAddons = services.addons?.mongodb || [];
if (mongoAddons.length === 0) {
throw new Error('No MongoDB addon configured');
}
  1. Provide default values:
const LOG_LEVEL = process.env.LOG_LEVEL || 'info';
const TIMEOUT = parseInt(process.env.TIMEOUT || '30000');
  1. Validate required variables on startup:
const required = ['DATABASE_URL', 'JWT_SECRET'];
const missing = required.filter(v => !process.env[v]);

if (missing.length > 0) {
throw new Error(`Missing required env vars: ${missing.join(', ')}`);
}
  1. Check manifest configuration:
env:
- name: DATABASE_URL
value: ""
required: true # Platform will enforce this
secret: true

Out of Memory (OOM) Errors​

Problem: Application killed due to memory limit

Symptoms:

  • The status bar's reason mentions "OOMKilled"
  • The app restarts frequently
  • "JavaScript heap out of memory"

Solutions:

  1. Give the app more memory: on its Overview tab, Edit the Size card (or pick a larger environment) and restart the app. The app runs at exactly the size you set.

  2. Optimize application code:

// Bad: Loading entire dataset
const data = await db.collection.find().toArray();

// Good: Use streaming or pagination
const cursor = db.collection.find();
for await (const doc of cursor) {
process(doc);
}
  1. Increase Node.js heap size:
CMD ["node", "--max-old-space-size=1536", "server.js"]
  1. Enable autoscaling with memory threshold (deployment autoscaling config, thresholds are integer percentages):
# Autoscaling config
memory_threshold: 70 # Scale before hitting limit (default: 80)

Service Connection Issues​

Database Connection Failures​

Problem: Cannot connect to database

Symptoms:

  • "ECONNREFUSED"
  • "Connection timeout"
  • "Authentication failed"

Solutions:

  1. Verify service is connected (using correct STRONGLY_SERVICES structure):
const data = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
const services = data.services || {};

// List all addon types
console.log('Addon types:', Object.keys(services.addons || {}));

// List all datasource types
console.log('Datasource types:', Object.keys(services.datasources || {}));
  1. Use correct access pattern:
// MongoDB addon
const mongoAddons = services.addons?.mongodb || [];
if (mongoAddons.length > 0) {
const mongo = mongoAddons[0];
const connectionString = mongo.connection?.connection_string;
console.log('MongoDB host:', mongo.connection?.host);
}

// PostgreSQL datasource
const pgSources = services.datasources?.postgres || [];
if (pgSources.length > 0) {
const pg = pgSources[0];
console.log('PG host:', pg.connection?.host);
console.log('PG auth:', pg.auth?.method);
}
  1. Test connection separately:
const { MongoClient } = require('mongodb');

async function testConnection() {
try {
const client = await MongoClient.connect(connectionString);
console.log('Connected to database');
await client.close();
} catch (err) {
console.error('Connection failed:', err.message);
}
}
  1. Check service health:
Navigate to Add-ons -> Click addon name -> Check status
Ensure addon is "Running"

AI Model API Errors​

Problem: Cannot call AI model

Symptoms:

  • "Unauthorized"
  • "Model not found"
  • Connection timeout

Solutions:

  1. Verify AI Gateway configuration:
const data = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
const aiGateway = data.services?.aigateway;

console.log('AI Gateway base URL:', aiGateway?.base_url);
console.log('Available models:', aiGateway?.available_models?.length);

// List models
for (const model of aiGateway?.available_models || []) {
console.log(` - ${model.display_name} (${model.vendor_model_id})`);
console.log(` Type: ${model.type}, Model Type: ${model.modelType}`);
}
  1. Check API request format:
const model = aiGateway.available_models[0];

const response = await fetch(`${aiGateway.base_url}/v1/chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Model-Id': model._id // Use the Strongly model ID
},
body: JSON.stringify({
model: model.vendor_model_id, // Use vendor model ID
messages: [{ role: 'user', content: 'Hello' }]
})
});

if (!response.ok) {
const error = await response.text();
console.error('API error:', error);
}
  1. Verify model is available (for self-hosted models):
Navigate to AI Gateway -> Models -> Check status
Ensure model is "Active"

Workflow Trigger Failures​

Problem: Cannot invoke workflow

Symptoms:

  • "Workflow not found"
  • "Workflow execution failed"
  • No response from workflow

Solutions:

  1. Verify workflow configuration:
const data = JSON.parse(process.env.STRONGLY_SERVICES || '{}');
const workflows = data.services?.workflows?.available_workflows || [];

for (const wf of workflows) {
console.log(`Workflow: ${wf.name} (${wf.id})`);
console.log(` Trigger: ${wf.trigger_type}`);
console.log(` URL: ${wf.endpoints?.proxy_url}`);
console.log(` Method: ${wf.endpoints?.method}`);
}
  1. Check request format:
const workflow = workflows[0];

const response = await fetch(workflow.endpoints.proxy_url, {
method: workflow.endpoints.method || 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
// Match the workflow's input_schema
input: 'data'
})
});

const result = await response.json();
console.log('Workflow result:', result);
  1. Verify workflow is active:
Navigate to Workflows -> Check workflow status
Ensure workflow is "Active" and deployed

Performance Issues​

High CPU Usage​

Problem: CPU usage consistently high

Solutions:

  1. Profile your application:
// Node.js CPU profiling
node --prof server.js
node --prof-process isolate-*.log > profile.txt
  1. Optimize hot code paths:
// Bad: Synchronous operation in request handler
app.get('/users', (req, res) => {
const data = fs.readFileSync('users.json'); // Blocks event loop
res.json(JSON.parse(data));
});

// Good: Asynchronous operation
app.get('/users', async (req, res) => {
const data = await fs.promises.readFile('users.json');
res.json(JSON.parse(data));
});
  1. Add caching:
const cache = new Map();

app.get('/users', async (req, res) => {
if (cache.has('users')) {
return res.json(cache.get('users'));
}

const users = await db.users.find().toArray();
cache.set('users', users);
setTimeout(() => cache.delete('users'), 60000); // 1 min TTL

res.json(users);
});
  1. Scale horizontally:
# Enable autoscaling (thresholds are integer percentages)
cpu_threshold: 60 # Lower threshold (default: 70)
max_replicas: 10

Slow Response Times​

Problem: API responses are slow

Solutions:

  1. Add database indexes:
-- Check slow queries
EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com';

-- Add index
CREATE INDEX idx_users_email ON users(email);
  1. Implement connection pooling:
// Bad: New connection per request
app.get('/users', async (req, res) => {
const client = new MongoClient(url);
await client.connect();
const users = await client.db().collection('users').find().toArray();
await client.close();
res.json(users);
});

// Good: Connection pool
const pool = new MongoClient(url, { maxPoolSize: 10 });
await pool.connect();

app.get('/users', async (req, res) => {
const users = await pool.db().collection('users').find().toArray();
res.json(users);
});
  1. Add pagination:
app.get('/users', async (req, res) => {
const page = parseInt(req.query.page) || 1;
const limit = 20;
const skip = (page - 1) * limit;

const users = await db.users
.find()
.skip(skip)
.limit(limit)
.toArray();

res.json({ users, page, hasMore: users.length === limit });
});

Deployment Issues​

Cannot Redeploy​

Problem: Redeploy doesn't work

Solutions:

  1. Check app status is not "Deploying"
  2. Wait for current operation to complete
  3. Try stopping and starting app first
  4. Contact support if stuck

Getting Help​

Diagnostic Information​

When contacting support, provide:

  1. App ID and Name
  2. Error logs from app details page
  3. Build logs if build failed
  4. Build status (pending, building, completed, failed, cancelled)
  5. Steps to reproduce the issue
  6. Screenshots of errors
  7. Manifest file content

Enable Debug Logging​

# manifest
env:
- name: LOG_LEVEL
value: "debug" # Or "DEBUG" for Python
// Node.js
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info'
});

Common Log Patterns​

Connection Refused:

Error: connect ECONNREFUSED 10.0.2.15:5432
-> Database not running or wrong host/port

Out of Memory:

<--- Last few GCs --->
FATAL ERROR: Reached heap limit
-> Increase memory limit or optimize code

Module Not Found:

Error: Cannot find module 'express'
-> Dependency not installed, check package.json

Port in Use:

Error: listen EADDRINUSE: address already in use :::3000
-> Port conflict, check manifest configuration

App Builder Unreachable:

Error: Cannot connect to app builder service
-> The platform could not take the deploy; retry, then contact your administrator

Next Steps​