Stack Debugging
Troubleshoot @outfitter/* package issues.
Result Issues
Always Getting Error
Symptom: Result is err when it should be ok.
Check validation:
const inputResult = validateInput(rawInput);
if (inputResult.isErr()) {
console.log("Validation failed:", inputResult.error.details);
return inputResult;
}
Check async:
// BAD: Missing await
const result = getUser(id); // Promise, not Result!
// GOOD
const result = await getUser(id);
Type Narrowing Broken
Symptom: TypeScript doesn't know type after isOk().
// BAD: Reassigning breaks narrowing
let result = await getUser(id);
if (result.isOk()) {
result = await updateUser(result.value); // Breaks!
}
// GOOD: Separate variables
const getResult = await getUser(id);
if (getResult.isErr()) return getResult;
const updateResult = await updateUser(getResult.value);
Error Type Lost
Use _tag for narrowing:
if (result.isErr()) {
switch (result.error._tag) {
case "ValidationError":
console.log(result.error.details);
break;
case "NotFoundError":
console.log(result.error.resourceId);
break;
}
}
MCP Issues
Tool Not Appearing
- Register before
start():
``typescript server.registerTool(myTool); server.start(); // After registration! ``
- Check schema is valid Zod with
.describe():
``typescript const schema = z.object({ query: z.string().describe("Required for AI"), }); ``
Tool Invocation Failing
- Verify handler is async:
``typescript handler: async (input) => { // Not sync! return Result.ok(data); } ``
- Return Result, not raw value:
```typescript // BAD return { data: "value" };
// GOOD return Result.ok({ data: "value" }); ```
CLI Output Issues
JSON Not Printing
- Force mode:
``typescript await output(data, { mode: "json" }); ``
- Check environment:
``bash OUTFITTERJSON=1 myapp list OUTFITTERJSON=0 myapp list --json # Forces human! ``
- Await output:
```typescript // BAD output(data); process.exit(0); // May exit before output!
// GOOD await output(data); ```
Wrong Exit Code
- Use
exitWithError:
```typescript // BAD process.exit(1);
// GOOD exitWithError(result.error); ```
- Exit code table:
| Category |
Exit |
| validation |
1 |
| not_found |
2 |
| conflict |
3 |
| permission |
4 |
| timeout |
5 |
| rate_limit |
6 |
| network |
7 |
| internal |
8 |
| auth |
9 |
| cancelled |
130 |
Logging Issues
Redaction Not Working
const logger = createLogger({
redaction: { enabled: true }, // Must be true!
});
// Custom patterns
const logger = createLogger({
redaction: {
enabled: true,
patterns: ["password", "apiKey", "myCustomSecret"],
},
});
Missing Context
import { createChildLogger } from "@outfitter/logging";
const requestLogger = createChildLogger(ctx.logger, {
requestId: ctx.requestId,
handler: "myHandler",
});
requestLogger.info("Processing", { data }); // Includes requestId
Wrong Level
const logger = createLogger({
level: process.env.LOG_LEVEL || "info",
});
// Hierarchy: trace < debug < info < warn < error < fatal
// "info" hides trace and debug
Debugging Tools
Trace Result Chain
function traceResult<T, E>(name: string, result: Result<T, E>): Result<T, E> {
console.log(`[${name}]`, result.isOk() ? "OK:" : "ERR:",
result.isOk() ? result.value : result.error);
return result;
}
const result = traceResult("getUser", await getUser(id));
Inspect Context
console.log("Context:", {
requestId: ctx.requestId,
hasLogger: !!ctx.logger,
hasConfig: !!ctx.config,
hasSignal: !!ctx.signal,
cwd: ctx.cwd,
});
Validate Zod Schema
const parseResult = schema.safeParse(rawInput);
if (!parseResult.success) {
console.log("Zod errors:", parseResult.error.issues);
}
Related Skills
outfitter-stack:stack-patterns — Correct patterns
outfitter-stack:stack-review — Systematic audit