different-ai/openwork · error
automation_saved_script_forbidden
automation_saved_script_forbidden
Error message
automation_saved_script_forbidden
What it means
Thrown in validateWorkflowAutomationAction when the automation's owner member is not an admin and holds no access grant — via direct membership grants or team grants — for either the referenced config object (saved script) or the referenced plugin, per resolvePluginArchGrantRole. Only owners with at least one such grant may automate the saved script.
Source
Thrown at ee/apps/den-api/src/workflows.ts:552
}).from(ConfigObjectAccessGrantTable).where(and(
eq(ConfigObjectAccessGrantTable.organizationId, organizationId),
eq(ConfigObjectAccessGrantTable.configObjectId, configObjectId),
)),
db.select({
orgMembershipId: PluginAccessGrantTable.orgMembershipId,
orgWide: PluginAccessGrantTable.orgWide,
removedAt: PluginAccessGrantTable.removedAt,
role: PluginAccessGrantTable.role,
teamId: PluginAccessGrantTable.teamId,
}).from(PluginAccessGrantTable).where(and(
eq(PluginAccessGrantTable.organizationId, organizationId),
eq(PluginAccessGrantTable.pluginId, pluginId),
)),
])
const grantInput = { memberId: ownerMemberId, teamIds: teams.map((team) => team.id) }
if (!resolvePluginArchGrantRole({ ...grantInput, grants: configObjectGrants })
&& !resolvePluginArchGrantRole({ ...grantInput, grants: pluginGrants })) {
throw new Error("automation_saved_script_forbidden")
}
}
const rows = await db.select({ version: ConfigObjectVersionTable })
.from(ConfigObjectVersionTable)
.innerJoin(ConfigObjectTable, and(
eq(ConfigObjectTable.id, ConfigObjectVersionTable.configObjectId),
eq(ConfigObjectTable.organizationId, organizationId),
eq(ConfigObjectTable.objectType, "workflow"),
eq(ConfigObjectTable.status, "active"),
isNull(ConfigObjectTable.deletedAt),
))
.innerJoin(PluginConfigObjectTable, and(
eq(PluginConfigObjectTable.configObjectId, ConfigObjectTable.id),
eq(PluginConfigObjectTable.pluginId, pluginId),
isNull(PluginConfigObjectTable.removedAt),
))
.where(and(
eq(ConfigObjectVersionTable.id, configObjectVersionId),View on GitHub (pinned to 2b7df46e8a)
Solutions
- Grant the owner member (or one of their teams) an access grant on the config object or plugin.
- Promote the owner to an org admin role, which bypasses the grant check.
- Choose a different owner who already has access to the saved script/plugin.
Example fix
// before
await createAutomation({ ownerMemberId: viewerId, configObjectId, pluginId })
// after
await db.insert(ConfigObjectAccessGrantTable).values({ orgMembershipId: viewerId, configObjectId, role: "editor" })
await createAutomation({ ownerMemberId: viewerId, configObjectId, pluginId }) Defensive patterns
Strategy: validation
Validate before calling
const isOwnerGranted = resolvePluginArchGrantRole({ memberId: ownerMemberId, teamIds, grants: configObjectGrants }) !== null
|| resolvePluginArchGrantRole({ memberId: ownerMemberId, teamIds, grants: pluginGrants }) !== null
if (!isAdmin && !isOwnerGranted) throw new Error("would fail: automation_saved_script_forbidden") Try / catch
try {
await createAutomation(input)
} catch (e) {
if (e.message === "automation_saved_script_forbidden") {
// add a ConfigObject/Plugin access grant for the owner or pick an admin owner
} else throw e
} Prevention
- Check owner grants (direct + team) before saving automations.
- Avoid revoking grants while dependent automations exist.
- Prefer admin owners for org-wide automations.
When it happens
Trigger: Creating/updating an automation whose ownerMemberId lacks both ConfigObjectAccessGrantTable and PluginAccessGrantTable coverage (directly or via TeamMemberTable teams) for the script's config object / plugin.
Common situations: Automation reassigned to a member without plugin access; team membership changed removing the needed team grant; a grant revoked while the automation edit was pending.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- automation_owner_inactive
- automation_saved_script_version_not_found
- automation_saved_script_version_invalid
- automation_saved_script_input_invalid
- invalid_mcp_connection_payload
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/757de13b1b51b4dc.
Report an issue: GitHub.