Repository: n8n-io/n8n
File: packages/cli/src/public-api/v1/handlers/executions/executions.handler.ts (TypeScript)

Code before:
			if (!sharedWorkflowsIds.length) {
				return res.status(404).json({ message: 'Not Found' });
			}

			const execution = await Container.get(
				ExecutionRepository,
			).getExecutionInWorkflowsForPublicApi(id, sharedWorkflowsIds, false);

			if (!execution) {
				return res.status(404).json({ message: 'Not Found' });
			}

			const annotation = await Container.get(ExecutionAnnotationRepository).findOne({
				where: { execution: { id } },
				relations: ['tags'],
			});

			const tags = (annotation?.tags ?? []).map(({ id: tagId, name, createdAt, updatedAt }) => ({
				id: tagId,
				name,
				createdAt,
				updatedAt,
			}));

			return res.json(tags);
		},
	],
	updateExecutionTags: [
		apiKeyHasScope('executionTags:update'),
		async (req: ExecutionRequest.UpdateTags, res: express.Response): Promise<express.Response> => {
			const { id } = req.params;
			const newTagIds = req.body.map((tag) => tag.id);
			const sharedWorkflowsIds = await getSharedWorkflowIds(req.user, ['workflow:read']);

			if (!sharedWorkflowsIds.length) {
				return res.status(404).json({ message: 'Not Found' });
			}

			const execution = await Container.get(
				ExecutionRepository,
			).getExecutionInWorkflowsForPublicApi(id, sharedWorkflowsIds, false);

			if (!execution) {
				return res.status(404).json({ message: 'Not Found' });
			}

			// Upsert annotation (create if it doesn't exist)
			await Container.get(ExecutionAnnotationRepository).upsert({ execution: { id } }, [
				'execution',
			]);


Review comment (bug):
This handler performs three separate DB operations (upsert annotation, overwrite tags, fetch updated tags) without a transaction. 
If something fails between the upsert and the overwriteTags, the annotation is created but tags aren't set. 

Code after:

			const execution = await Container.get(
				ExecutionRepository,
			).getExecutionInWorkflowsForPublicApi(id, sharedWorkflowsIds, false);

			if (!execution) {
				return res.status(404).json({ message: 'Not Found' });
			}

			const tags = await getExecutionTags(id);

			return res.json(tags);
		},
	],
	updateExecutionTags: [
		apiKeyHasScope('executionTags:update'),
		async (req: ExecutionRequest.UpdateTags, res: express.Response): Promise<express.Response> => {
			const { id } = req.params;
			const newTagIds = req.body.map((tag) => tag.id);
			const sharedWorkflowsIds = await getSharedWorkflowIds(req.user, ['workflow:update']);

			if (!sharedWorkflowsIds.length) {
				return res.status(404).json({ message: 'Not Found' });
			}

			const execution = await Container.get(
				ExecutionRepository,
			).getExecutionInWorkflowsForPublicApi(id, sharedWorkflowsIds, false);

			if (!execution) {
				return res.status(404).json({ message: 'Not Found' });
			}

			try {
				const updatedTags = await updateExecutionTags(id, newTagIds);
				const tags = mapAnnotationTags(updatedTags);
				return res.json(tags);
			} catch (error) {
				if (error instanceof QueryFailedError) {
					return res.status(404).json({ message: 'Some tags not found' });
				}
				throw error;
			}
		},
	],
};