{"record":{"id":"2f74a3fce0854546","repo":"remotion-dev/remotion","slug":"no-effects-were-specified-for-duplication-effect-operations","errorCode":null,"errorMessage":"No effects were specified for duplication","messagePattern":"No effects were specified for duplication","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/studio-codemods/src/effect-operations.ts","lineNumber":463,"sourceCode":"\t\t};\n\t});\n\nexport const duplicateEffects = ({\n\teffects,\n\tinput,\n\tprettierConfigOverride,\n}: {\n\teffects: EffectTarget[];\n\tinput: string;\n} & EffectSourceStyleOptions): Promise<{\n\toutput: string;\n\tformatted: boolean;\n\teffectLabels: string[];\n\tlogLines: number[];\n}> =>\n\tPromise.resolve().then(() => {\n\t\tif (effects.length === 0) {\n\t\t\tthrow new Error('No effects were specified for duplication');\n\t\t}\n\n\t\tconst ast = parseAst(input);\n\t\tconst snapshots = captureEffectSourceSnapshots(ast);\n\t\tconst effectsByAttribute = new Map<\n\t\t\tJSXAttribute,\n\t\t\t{\n\t\t\t\tarray: ArrayExpression;\n\t\t\t\tindices: Set<number>;\n\t\t\t\teffectLabels: string[];\n\t\t\t\tlogLines: number[];\n\t\t\t}\n\t\t>();\n\t\tfor (const {effectIndex, sequenceNodePath} of effects) {\n\t\t\tconst jsx = getJsx({action: 'duplicate', ast, sequenceNodePath});\n\t\t\tconst attr = findEffectsAttr(jsx.attributes);\n\t\t\tif (!attr) {\n\t\t\t\tthrow new Error('Could not find effects on the target JSX element');","sourceCodeStart":445,"sourceCodeEnd":481,"githubUrl":"https://github.com/remotion-dev/remotion/blob/46a3a6bf13ca367376ff18bbb06dae2e87e0d068/packages/studio-codemods/src/effect-operations.ts#L445-L481","documentation":"duplicateEffects requires at least one effect target ({effectIndex, sequenceNodePath}) to operate on. It is the batch API behind duplicateEffect; calling it with an empty `effects` array is a caller error and throws immediately, before any parsing occurs.","triggerScenarios":"Calling duplicateEffects({input, effects: []}); calling duplicateEffect after effects computed asynchronously produced an empty selection.","commonSituations":"A Studio UI selection that was already emptied (effects deleted elsewhere) before the duplicate action dispatched; filtering out invalid targets leaving an empty list.","solutions":["Guard the effects array length before calling and skip/no-op when empty","Ensure at least one valid {effectIndex, sequenceNodePath} entry is passed","If this comes from UI state, re-validate the current selection when the action fires"],"exampleFix":"// before\nduplicateEffects({input, effects: []});\n// after\nif (effects.length > 0) { await duplicateEffects({input, effects}); }","handlingStrategy":"validation","validationCode":"if (!Array.isArray(effects) || effects.length === 0) return null; // no-op instead of calling\nduplicateEffects({input, effects});","typeGuard":"const hasEffects = (e: EffectTarget[]): e is [EffectTarget, ...EffectTarget[]] => e.length > 0;","tryCatchPattern":"try { await duplicateEffects({input, effects}); } catch (e) { if ((e as Error).message === 'No effects were specified for duplication') return null; throw e; }","preventionTips":["Check selection emptiness before dispatching duplicate actions","Filter invalid targets first; if none remain, skip the call","Treat empty selection as a UI no-op, not an error path"],"tags":["validation","effects","empty-input"],"backgroundTag":"empty-required-field","analyzedSha":"46a3a6bf13ca367376ff18bbb06dae2e87e0d068","analyzedAt":"2026-09-18T00:12:20.256Z","contentChangedAt":"2026-09-18T00:12:20.256Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}