Bug
Clicking "Update Plugin" on a plugin whose rules have long description frontmatter fails with:
Failed to update plugin: new row for relation "plugin_components" violates check constraint "plugin_components_slug_length_check"
Root cause
The slugify function in edit-plugin-form.tsx (and the one in update-plugin.ts) is missing the .slice(0, 80) truncation that exists in both parse.ts and insert.ts:
// edit-plugin-form.tsx — missing truncation
function slugify(value: string) {
return value
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
Compare with parse.ts / insert.ts:
const MAX_SLUG_LENGTH = 80;
function slugify(value: string) {
return value
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "")
.slice(0, MAX_SLUG_LENGTH)
.replace(/-+$/g, "");
}
Additionally, the edit form (EditableComponent type) discards the original slug when loading existing components from the database. On submit, it regenerates slugs from comp.name — which for rules is the description frontmatter (a full sentence), not the short filename. This produces slugs well over 80 characters.
Steps to reproduce
- Publish a plugin with rules that have long
description frontmatter (e.g. > 80 chars when slugified)
- Go to the plugin's edit page
- Click "Update Plugin" (even without making changes)
- Observe the
plugin_components_slug_length_check constraint violation
Affected plugin
https://cursor.directory/plugins/cadence — 22 of 34 rules produce description-derived slugs over 80 characters. Initial creation works fine (insert path caps at 80); only the update path fails.
Suggested fix
edit-plugin-form.tsx: Preserve the original slug from the database in the EditableComponent type, and pass it through on submit instead of regenerating it from name.
edit-plugin-form.tsx: Add .slice(0, 80).replace(/-+$/, "") to the client-side slugify as a safety net.
update-plugin.ts: Add .slice(0, 80).replace(/-+$/, "") to the server-side slugify as belt-and-suspenders.
Related: migration 20260513_plugin_component_slug_length.sql and commit b99b94e ("chore: trigger rebuild after slug-length data fix") addressed slug length in the insert/parse paths but missed the update path.
Bug
Clicking "Update Plugin" on a plugin whose rules have long
descriptionfrontmatter fails with:Root cause
The
slugifyfunction inedit-plugin-form.tsx(and the one inupdate-plugin.ts) is missing the.slice(0, 80)truncation that exists in bothparse.tsandinsert.ts:Compare with
parse.ts/insert.ts:Additionally, the edit form (
EditableComponenttype) discards the originalslugwhen loading existing components from the database. On submit, it regenerates slugs fromcomp.name— which for rules is thedescriptionfrontmatter (a full sentence), not the short filename. This produces slugs well over 80 characters.Steps to reproduce
descriptionfrontmatter (e.g. > 80 chars when slugified)plugin_components_slug_length_checkconstraint violationAffected plugin
https://cursor.directory/plugins/cadence — 22 of 34 rules produce description-derived slugs over 80 characters. Initial creation works fine (insert path caps at 80); only the update path fails.
Suggested fix
edit-plugin-form.tsx: Preserve the originalslugfrom the database in theEditableComponenttype, and pass it through on submit instead of regenerating it fromname.edit-plugin-form.tsx: Add.slice(0, 80).replace(/-+$/, "")to the client-sideslugifyas a safety net.update-plugin.ts: Add.slice(0, 80).replace(/-+$/, "")to the server-sideslugifyas belt-and-suspenders.Related: migration
20260513_plugin_component_slug_length.sqland commitb99b94e("chore: trigger rebuild after slug-length data fix") addressed slug length in the insert/parse paths but missed the update path.