grafana/grafana · error · Error
Annotation '${name}' already exists
Error message
Annotation '${name}' already exists What it means
Thrown by the ADD_ANNOTATION dashboard-scene mutation command when a new annotation layer's spec.name collides with an existing annotation layer in the dashboard's annotation layer set. The command is wrapped in try/catch and converts the thrown Error into a { success:false, error } result, so callers see a failed mutation result rather than a propagated exception.
Source
Thrown at public/app/features/dashboard-scene/mutation-api/commands/addAnnotation.ts:42
name: 'ADD_ANNOTATION',
description: payloads.addAnnotation.description ?? '',
payloadSchema: payloads.addAnnotation,
permission: requiresEdit,
readOnly: false,
handler: async (payload, context) => {
const { scene } = context;
enterEditModeIfNeeded(scene);
try {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- Zod output is structurally compatible with AnnotationQueryKind
const annotation = payload.annotation as AnnotationQueryKind;
const name = annotation.spec.name;
const set = getAnnotationLayerSet(scene);
if (findAnnotationLayer(set, name)) {
throw new Error(`Annotation '${name}' already exists`);
}
if (annotation.spec.builtIn && hasBuiltInAnnotation(set)) {
throw new Error('Dashboard already has a built-in annotation layer');
}
const newLayer = buildAnnotationLayer(annotation);
const updated = [...set.state.annotationLayers];
const { position } = payload;
if (position !== undefined && position >= 0 && position < updated.length) {
updated.splice(position, 0, newLayer);
} else {
updated.push(newLayer);
}
replaceAnnotationLayers(set, updated);
View on GitHub (pinned to ae3104e369)
Solutions
- Choose a unique annotation layer name (check findAnnotationLayer(set, name) first).
- If overwriting was intended, use the update/replace command instead of ADD_ANNOTATION.
- Surface the returned result.error in the UI when success === false.
- In tests, use unique names per command.
Example fix
// before
const res = await runMutation({ type: 'ADD_ANNOTATION', annotation });
// after
const set = getAnnotationLayerSet(scene);
if (findAnnotationLayer(set, annotation.spec.name)) {
notify.error(`Annotation '${annotation.spec.name}' already exists`);
return;
}
const res = await runMutation({ type: 'ADD_ANNOTATION', annotation }); Defensive patterns
Strategy: validation
Validate before calling
const set = getAnnotationLayerSet(scene);
if (findAnnotationLayer(set, annotation.spec.name)) {
notify.error(`Annotation '${annotation.spec.name}' already exists`);
return;
} Type guard
const isUniqueAnnotationName = (set, name): boolean => !findAnnotationLayer(set, name);
Try / catch
const res = await runMutation({ type: 'ADD_ANNOTATION', annotation });
if (!res.success) {
notify.error(res.error);
} Prevention
- Check findAnnotationLayer before issuing ADD_ANNOTATION.
- Use the update command for overwrite intent.
- Always read result.success and surface result.error.
When it happens
Trigger: Issuing ADD_ANNOTATION with payload.annotation.spec.name equal to the spec.name of an existing layer in getAnnotationLayerSet(scene).state.annotationLayers.
Common situations: User creates an annotation layer with a duplicate name; programmatic dashboards issuing multiple ADD_ANNOTATION commands with the same name; copy-paste of annotation specs; tests that re-use a name without clearing the set.
Related errors
- Annotation '${name}' not found
- Annotation '${name}' not found
- Dashboard already has a built-in annotation layer
- Invalid layout path "${path}": expected /type/index pairs
- Invalid layout path "${path}": unknown segment type "${type}
AI-assisted analysis of grafana/grafana@ae3104e369 (2026-08-12).
Data as JSON: /api/errors/0d8b0668c5bb7c85.
Report an issue: GitHub.