anomalyco/sst · error · VisibleError
Cannot set both "logging.retention" and "logging.logGroup"
Error message
Cannot set both "logging.retention" and "logging.logGroup"
What it means
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`.
Source
Thrown at platform/src/components/aws/function.ts:1943
}
if (streaming) {
result.SST_FUNCTION_STREAMING = "true";
}
}
return result;
});
}
function normalizeStreaming() {
return output(args.streaming).apply((streaming) => streaming ?? false);
}
function normalizeLogging() {
return output(args.logging).apply((logging) => {
if (logging === false) return undefined;
if (logging?.retention && logging?.logGroup) {
throw new VisibleError(
`Cannot set both "logging.retention" and "logging.logGroup"`,
);
}
if (args.durable && logging?.format && logging?.format != "json") {
throw new VisibleError(
`Durable functions require "logging.format" to be set to "json"`,
);
}
const defaultFormat = args.durable ? "json" : "text";
return {
logGroup: logging?.logGroup,
retention: logging?.retention ?? "1 month",
format: logging?.format ?? defaultFormat,
};
});View on GitHub (pinned to a0bd20f762)
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
Example fix
// before
logging: { retention: "1 week", logGroup: myGroup }
// after
logging: { logGroup: myGroup } Defensive patterns
Strategy: validation
Validate before calling
if (args.logging && typeof args.logging === "object" && "retention" in args.logging && "logGroup" in args.logging)
throw new Error("Set either logging.retention or logging.logGroup, not both"); Type guard
function hasLoggingConflict(logging: unknown): boolean {
return !!logging && typeof logging === "object" &&
"retention" in logging && "logGroup" in logging;
} Try / catch
try {
const fn = new sst.aws.Function("Fn", args);
} catch (e) {
if ((e as Error).message.includes("logging.retention")) {
console.error("Choose one: managed log group (retention) or existing logGroup");
}
throw e;
} Prevention
- 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
When it happens
Trigger: Passing both `logging: { retention: "1 week", logGroup: someLogGroup }` in Function args.
Common situations: 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.
Related errors
- Durable functions require "logging.format" to be set to "jso
- Only one of function, queue, or topic is allowed for the "${
- You must provide a KMS key via `kmsKey` when configuring `cu
- type === "service" ? `You cannot provide both "containers" a
- Copy destination path "${to}" must be relative
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/a5efaaa54e2d1101.
Report an issue: GitHub.