diff --git a/server/src/services/placeService.ts b/server/src/services/placeService.ts index 21a91ea5..0f8c51a8 100644 --- a/server/src/services/placeService.ts +++ b/server/src/services/placeService.ts @@ -719,6 +719,11 @@ export async function importGoogleList(tripId: string, url: string, opts?: ListI } if (!listId) { + // A single-place share link (…/maps/place/…) carries no list id — point the user at + // the place search box instead of a cryptic "could not extract list ID" (#1304). + if (resolvedUrl.includes('/maps/place/')) { + return { error: 'That link points to a single place, not a list. To add it, paste the link into the place search box instead of using the list import.', status: 400 }; + } return { error: 'Could not extract list ID from URL. Please use a shared Google Maps list link.', status: 400 }; } diff --git a/server/tests/unit/services/placeService.test.ts b/server/tests/unit/services/placeService.test.ts index 2fc0b2d0..ad0b0016 100644 --- a/server/tests/unit/services/placeService.test.ts +++ b/server/tests/unit/services/placeService.test.ts @@ -416,6 +416,15 @@ describe('importGoogleList', () => { expect(result.status).toBe(400); }); + it('PLACE-SVC-026b — a single-place link gives a guiding error instead of the generic one (#1304)', async () => { + const { user } = createUser(testDb); + const trip = createTrip(testDb, user.id); + const url = 'https://www.google.com/maps/place/Eiffel+Tower/@48.8584,2.2945,17z/data=!3m1'; + const result = await importGoogleList(String(trip.id), url) as any; + expect(result.status).toBe(400); + expect(result.error).toMatch(/single place/i); + }); + it('PLACE-SVC-027 — returns error when Google Maps API responds with non-ok status', async () => { const { user } = createUser(testDb); const trip = createTrip(testDb, user.id);