{"record":{"id":"a5efaaa54e2d1101","repo":"anomalyco/sst","slug":"cannot-set-both-logging-retention-and-logging-l","errorCode":null,"errorMessage":"Cannot set both \"logging.retention\" and \"logging.logGroup\"","messagePattern":"Cannot set both \"logging\\.retention\" and \"logging\\.logGroup\"","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/function.ts","lineNumber":1943,"sourceCode":"          }\n          if (streaming) {\n            result.SST_FUNCTION_STREAMING = \"true\";\n          }\n        }\n        return result;\n      });\n    }\n\n    function normalizeStreaming() {\n      return output(args.streaming).apply((streaming) => streaming ?? false);\n    }\n\n    function normalizeLogging() {\n      return output(args.logging).apply((logging) => {\n        if (logging === false) return undefined;\n\n        if (logging?.retention && logging?.logGroup) {\n          throw new VisibleError(\n            `Cannot set both \"logging.retention\" and \"logging.logGroup\"`,\n          );\n        }\n\n        if (args.durable && logging?.format && logging?.format != \"json\") {\n          throw new VisibleError(\n            `Durable functions require \"logging.format\" to be set to \"json\"`,\n          );\n        }\n\n        const defaultFormat = args.durable ? \"json\" : \"text\";\n\n        return {\n          logGroup: logging?.logGroup,\n          retention: logging?.retention ?? \"1 month\",\n          format: logging?.format ?? defaultFormat,\n        };\n      });","sourceCodeStart":1925,"sourceCodeEnd":1961,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/function.ts#L1925-L1961","documentation":"normalizeLogging() in the SST Function component validates that you don't configure the log group in two ways at once. `logging.retention` implicitly creates a log group for you, so it conflicts with an explicitly provided `logging.logGroup`.","triggerScenarios":"Passing both `logging: { retention: \"1 week\", logGroup: someLogGroup }` in Function args.","commonSituations":"Migrating from retention-based logging to a pre-provisioned log group (e.g. shared with CloudWatch alarms) but forgetting to delete the retention field; code-generated configs that set all logging keys unconditionally.","solutions":["Remove `logging.retention` and keep `logging.logGroup` if you manage your own log group","Or remove `logging.logGroup` and keep `retention` to let SST create the log group"],"exampleFix":"// before\nlogging: { retention: \"1 week\", logGroup: myGroup }\n// after\nlogging: { logGroup: myGroup }","handlingStrategy":"validation","validationCode":"if (args.logging && typeof args.logging === \"object\" && \"retention\" in args.logging && \"logGroup\" in args.logging)\n  throw new Error(\"Set either logging.retention or logging.logGroup, not both\");","typeGuard":"function hasLoggingConflict(logging: unknown): boolean {\n  return !!logging && typeof logging === \"object\" &&\n    \"retention\" in logging && \"logGroup\" in logging;\n}","tryCatchPattern":"try {\n  const fn = new sst.aws.Function(\"Fn\", args);\n} catch (e) {\n  if ((e as Error).message.includes(\"logging.retention\")) {\n    console.error(\"Choose one: managed log group (retention) or existing logGroup\");\n  }\n  throw e;\n}","preventionTips":["Use retention when SST should create the log group; use logGroup only for pre-existing groups","When adding logGroup to an existing function, remove retention in the same change"],"tags":["aws","lambda","logging","config-conflict"],"backgroundTag":"mutually-exclusive-config-options","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}