---
title: "Boot Checks & Health"
description: "Create `server/env.ts` to validate required env vars."
canonical_url: "https://vercel.com/academy/slack-agents/boot-checks-and-health"
md_url: "https://vercel.com/academy/slack-agents/boot-checks-and-health.md"
docset_id: "vercel-academy"
doc_version: "1.0"
last_updated: "2026-04-09T11:39:00.980Z"
content_type: "lesson"
course: "slack-agents"
course_title: "Slack Agents on Vercel with the AI SDK"
prerequisites:  []
---

<agent-instructions>
Vercel Academy — structured learning, not reference docs.
Lessons are sequenced.
Adapt commands to the human's actual environment (OS, package manager, shell, editor) — detect from project context or ask, don't assume.
The lesson shows one path; if the human's project diverges, adapt concepts to their setup.
Preserve the learning goal over literal steps.
Quizzes are pedagogical — engage, don't spoil.
Quiz answers are included for your reference.
</agent-instructions>

# Boot Checks & Health

# Fail fast on misconfiguration, not during production

Missing env vars cause runtime errors deep in the stack instead of failing at boot. "not\_authed" at request time when the real issue is a missing token at startup. Boot checks catch these instantly before any code runs.

**After this lesson, you'll:**

- Remove an env var → app fails instantly with clear error message
- See `Environment validation failed` instead of cryptic runtime errors
- Get type-safe autocomplete for `env.SLACK_BOT_TOKEN` throughout your code

```bash
# ❌ Before boot checks (confusing):
$ slack run
[ERROR] UnhandledPromiseRejectionWarning: Error: An API error occurred: not_authed
    at validateToken (node_modules/@slack/web-api/dist/WebClient.js:789:23)

# ✅ After boot checks (explicit):
$ slack run
Invalid environment configuration: [{
  "path": ["SLACK_BOT_TOKEN"],
  "message": "SLACK_BOT_TOKEN is required"
}]
Error: Environment validation failed
```

## Outcome

Harden the repo so it fails fast on environment misconfigurations, missing secrets, and also confirms AI connectivity.

## Fast Track

1. Create `server/env.ts` with Zod schema for required env vars
2. Import at top of `app.ts` to validate on boot
3. Test by removing an env var and confirming fail-fast behavior

### Using Zod for env validation

\*\*Note: Why Zod?\*\*

[Zod](https://zod.dev) is a TypeScript-first schema validation library. You define what data should look like, and Zod validates it at runtime while providing type safety. You'll use the pattern of defining a schema → `safeParse()` → handle success/errors throughout the course.

Create `server/env.ts` to validate required environment variables at boot:

```typescript title="/server/env.ts"
import { z } from "zod";

export const envSchema = z.object({
  SLACK_SIGNING_SECRET: z.string().min(1, "SLACK_SIGNING_SECRET is required"),
  SLACK_BOT_TOKEN: z.string().min(1, "SLACK_BOT_TOKEN is required"),
  // AI gateway auth can come from an explicit API key or from Vercel's OIDC integration.
  // We don't hard-require either here to keep boot checks focused on Slack secrets.
  AI_GATEWAY_API_KEY: z.string().optional(),
  NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
});

const result = envSchema.safeParse(process.env);

if (!result.success) {
  console.error("Invalid environment configuration:", result.error.issues);
  throw new Error("Environment validation failed");
}

export const env = result.data;
```

Import the `env` module at the top of `server/app.ts` to fail fast during startup. Replace all `process.env.*` references with `env.*`:

```typescript title="/server/app.ts" {4, 7, 14-15}
import { App, LogLevel } from "@slack/bolt";
import { VercelReceiver } from "@vercel/slack-bolt";
import registerListeners from "./listeners";
import { env } from "./env";

const logLevel =
  env.NODE_ENV === "development" ? LogLevel.DEBUG : LogLevel.INFO;

const receiver = new VercelReceiver({
  logLevel,
});

const app = new App({
  token: env.SLACK_BOT_TOKEN,
  signingSecret: env.SLACK_SIGNING_SECRET,
  receiver,
  deferInitialization: true,
  logLevel,
});

registerListeners(app);

export { app, receiver };
```

**Note:** You'll also need to update any other files that reference `process.env.SLACK_BOT_TOKEN`, `process.env.SLACK_SIGNING_SECRET`, or `process.env.AI_GATEWAY_API_KEY` to use the `env` object instead. The main touchpoint is `server/app.ts`, but check listeners and utilities if you added direct `process.env` references elsewhere.

## Try It

1. **Test fail-fast behavior:**
   - Comment out `SLACK_BOT_TOKEN` in `.env`
   - Run `slack run` — it should fail immediately with:
     ```
     Invalid environment configuration: [
       {
         "path": ["SLACK_BOT_TOKEN"],
         "message": "SLACK_BOT_TOKEN is required"
       }
     ]
     Error: Environment validation failed
     ```

2. **Restore and verify:**
   - Uncomment `SLACK_BOT_TOKEN`
   - Run `slack run` — app starts successfully

## Commit

```bash
git add -A
git commit -m "feat(boot): add environment validation with Zod

- Create env.ts with required variable schema
- Fail fast on missing or invalid configuration
- Type-safe environment variable access throughout app"
```

## Done-When

- [x] Created `server/env.ts` with Zod validation schema
- [x] App fails immediately when required env vars are missing
- [x] Type-safe access to environment variables via `env` object


---

[Full course index](/academy/llms.txt) · [Sitemap](/academy/sitemap.md)
