From 6c95013f240bbe71a1575e8c5d4fa56f5fe50c9c Mon Sep 17 00:00:00 2001 From: David Montero Date: Thu, 9 Apr 2026 02:34:43 +0200 Subject: [PATCH] fix: prevent save to /api/projects/none when project ID is invalid Two bugs causing "can't save project" reports: 1. SaveProjectModal: validate currentProject.id is a real UUID before calling updateProject. If id is "none" or any non-UUID string, fall through to createProject instead, avoiding PUT /api/projects/none. 2. ProjectByIdPage: call clearCurrentProject() when the project fetch fails (404/403/error). Prevents stale project IDs from a previous session polluting the store and triggering spurious update calls. --- frontend/src/components/layout/SaveProjectModal.tsx | 8 ++++++-- frontend/src/pages/ProjectByIdPage.tsx | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/layout/SaveProjectModal.tsx b/frontend/src/components/layout/SaveProjectModal.tsx index 4d0b0730..4ffb9c5d 100644 --- a/frontend/src/components/layout/SaveProjectModal.tsx +++ b/frontend/src/components/layout/SaveProjectModal.tsx @@ -58,15 +58,19 @@ export const SaveProjectModal: React.FC = ({ onClose }) = wires_json: JSON.stringify(wires), }; + const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; + const isValidUpdate = isUpdate && currentProject && UUID_RE.test(currentProject.id); + try { let saved; - if (isUpdate && currentProject) { - saved = await updateProject(currentProject.id, payload); + if (isValidUpdate) { + saved = await updateProject(currentProject!.id, payload); trackSaveProject(); } else { saved = await createProject(payload); trackCreateProject(); } + setCurrentProject({ id: saved.id, slug: saved.slug, diff --git a/frontend/src/pages/ProjectByIdPage.tsx b/frontend/src/pages/ProjectByIdPage.tsx index 5c32cc4d..a6f69e5a 100644 --- a/frontend/src/pages/ProjectByIdPage.tsx +++ b/frontend/src/pages/ProjectByIdPage.tsx @@ -19,6 +19,7 @@ export const ProjectByIdPage: React.FC = () => { const loadFiles = useEditorStore((s) => s.loadFiles); const { setComponents, setWires, setBoardType } = useSimulatorStore(); const setCurrentProject = useProjectStore((s) => s.setCurrentProject); + const clearCurrentProject = useProjectStore((s) => s.clearCurrentProject); const currentProject = useProjectStore((s) => s.currentProject); const [ready, setReady] = useState(false); const [error, setError] = useState(''); @@ -56,6 +57,7 @@ export const ProjectByIdPage: React.FC = () => { if (s === 404) setError('Project not found.'); else if (s === 403) setError('This project is private.'); else setError('Failed to load project.'); + clearCurrentProject(); }); }, [id]);