diff --git a/.changeset/case-link-validation-message.md b/.changeset/case-link-validation-message.md new file mode 100644 index 00000000..267ab30c --- /dev/null +++ b/.changeset/case-link-validation-message.md @@ -0,0 +1,5 @@ +--- +'aicodeman': patch +--- + +Link Existing now says what is wrong when it rejects a case. A bad name reports "Invalid case name format" and a bad folder path reports why (not absolute, a character a session folder cannot have, ...), instead of the same "Invalid request body" for both. diff --git a/src/web/routes/case-routes.ts b/src/web/routes/case-routes.ts index 7515e1da..66a073f0 100644 --- a/src/web/routes/case-routes.ts +++ b/src/web/routes/case-routes.ts @@ -1536,7 +1536,7 @@ export function registerCaseRoutes(app: FastifyInstance, ctx: EventPort & Config // admin-only in multi-user mode (mirrors host CRUD + the admin-only GET listing). const denied = adminOnly(req, reply); if (denied) return denied; - const { name, path: folderPath } = parseBody(LinkCaseSchema, req.body, 'Invalid request body'); + const { name, path: folderPath } = parseBody(LinkCaseSchema, req.body); // Expand ~ to home directory const expandedPath = folderPath.startsWith('~') ? join(homedir(), folderPath.slice(1)) : folderPath; diff --git a/test/routes/case-routes.test.ts b/test/routes/case-routes.test.ts index c0fdcce8..c78bfa0f 100644 --- a/test/routes/case-routes.test.ts +++ b/test/routes/case-routes.test.ts @@ -647,6 +647,25 @@ describe('case-routes', () => { expect(body.success).toBe(false); }); + it('says which field is wrong instead of a generic message', async () => { + const badName = await harness.app.inject({ + method: 'POST', + url: '/api/cases/link', + payload: { name: 'bad name!', path: '/home/user/project' }, + }); + expect(badName.statusCode).toBe(400); + expect(JSON.parse(badName.body).error).toBe('Invalid case name format'); + + // A leading `~` is expanded later in the route but fails the absolute-path rule first. + const badPath = await harness.app.inject({ + method: 'POST', + url: '/api/cases/link', + payload: { name: 'my-project', path: '~/project' }, + }); + expect(badPath.statusCode).toBe(400); + expect(JSON.parse(badPath.body).error).toMatch(/^Invalid path:/); + }); + it('returns not found when folder does not exist', async () => { mockedExistsSync.mockReturnValue(false);