fix: daemon warns instead of crashing on missing OpenAI speech credentials (#1368)

* fix: daemon warns instead of crashing on missing OpenAI speech credentials

validateOpenAiCredentialRequirements was throwing an error when
OpenAI speech providers were configured without credentials,
causing the daemon to crash before it could start serving health
checks. Changed to log a warning instead — the daemon starts
successfully and reports speech services as unavailable.

Closes #1367

* chore: address Greptile review feedback

- Remove duplicate warning in initializeOpenAiSpeechServices when
  all credentials are missing (already warned by validate)
- Strengthen test assertions: check getListenTarget() after start
- Wrap daemon start/stop in try/finally for proper cleanup on failure
This commit is contained in:
Matt Cowger
2026-06-18 20:09:39 -07:00
committed by GitHub
parent d0189f3f65
commit b90baaff71
2 changed files with 12 additions and 10 deletions

View File

@@ -339,7 +339,7 @@ describe("paseo daemon bootstrap", () => {
}
});
test("fails fast when OpenAI speech provider is configured without credentials", async () => {
test("starts when OpenAI speech provider is configured without credentials", async () => {
const paseoHomeRoot = await mkdtemp(path.join(os.tmpdir(), "paseo-openai-config-"));
const paseoHome = path.join(paseoHomeRoot, ".paseo");
const staticDir = await mkdtemp(path.join(os.tmpdir(), "paseo-static-"));
@@ -368,9 +368,14 @@ describe("paseo daemon bootstrap", () => {
};
try {
await expect(createPaseoDaemon(config, pino({ level: "silent" }))).rejects.toThrow(
"Missing OpenAI credentials",
);
const daemon = await createPaseoDaemon(config, pino({ level: "silent" }));
try {
await daemon.start();
expect(daemon.getListenTarget()).toBeDefined();
// Must also stop without throwing
} finally {
await daemon.stop();
}
} finally {
await rm(paseoHomeRoot, { recursive: true, force: true });
await rm(staticDir, { recursive: true, force: true });

View File

@@ -85,7 +85,7 @@ export function validateOpenAiCredentialRequirements(params: {
}
if (missingOpenAiCredentialsFor.length > 0) {
logger.error(
logger.warn(
{
requestedProviders: {
dictationStt: providers.dictationStt.provider,
@@ -94,10 +94,7 @@ export function validateOpenAiCredentialRequirements(params: {
},
missingOpenAiCredentialsFor,
},
"Invalid speech configuration: OpenAI provider selected but credentials are missing",
);
throw new Error(
`Missing OpenAI credentials for configured speech features: ${missingOpenAiCredentialsFor.join(", ")}`,
"Invalid speech configuration: OpenAI provider selected but credentials are missing — speech features will be unavailable",
);
}
}
@@ -195,7 +192,7 @@ export function initializeOpenAiSpeechServices(params: {
);
}
} else if (needsAnyOpenAi) {
logger.warn("OpenAI speech providers are configured but credentials are missing");
// validateOpenAiCredentialRequirements already warned about missing credentials
}
return {