QuestPDF/QuestPDF · error · DocumentComposeException
The 'Decoration.Before' layer has already been defined. Plea
Error message
The 'Decoration.Before' layer has already been defined. Please call this method only once.
What it means
A Decoration has three named layers — Before, Content, After — and each may be defined only once. Calling .Before() (or the Before(handler) overload) a second time throws DocumentComposeException because the layer is already populated. Only an Empty or DebugPointer placeholder counts as 'undefined'.
Source
Thrown at src/dotnet/library/QuestPDF/Fluent/DecorationExtensions.cs:27
public sealed class DecorationDescriptor
{
internal Decoration Decoration { get; } = new Decoration();
internal DecorationDescriptor()
{
}
/// <summary>
/// Returns a container for the section positioned before (above) the primary main content.
/// </summary>
/// <remarks>
/// This container is fully visible on each page and does not support paging.
/// </remarks>
public IContainer Before()
{
if (Decoration.Before is not (Empty or DebugPointer))
throw new DocumentComposeException("The 'Decoration.Before' layer has already been defined. Please call this method only once.");
var container = new Container();
Decoration.Before = container;
return container
.DebugPointer(DebugPointerType.ElementStructure, "Before")
.RepeatAsHeader();
}
/// <summary>
/// Provides a handler to the section that appears before (above) the main content.
/// </summary>
/// <remarks>
/// This container is fully visible on each page and does not support paging.
/// </remarks>
public void Before(Action<IContainer> handler)
{
handler?.Invoke(Before());View on GitHub (pinned to 43ab125596)
Solutions
- Define Before exactly once per Decoration; branch the content inside that single call.
- If you need conditional header content, build it inside the one Before() lambda.
- Search for all .Before( calls on the same decoration instance and consolidate them.
Example fix
// before
decoration.Before().Text("Header");
// later
decoration.Before().Text("Other"); // throws
// after
decoration.Before(b => b.Text(showOther ? "Other" : "Header")); Defensive patterns
Strategy: validation
Validate before calling
// Structural guard: define Before in exactly one place. If you cannot guarantee that,
// track it with a flag:
bool beforeDefined = false;
if (!beforeDefined) { decoration.Before(b => b.Text(header)); beforeDefined = true; } Try / catch
try
{
decoration.Before(b => b.Text(header));
}
catch (DocumentComposeException ex) when (ex.Message.Contains("Decoration.Before"))
{
// Before was already defined elsewhere; consolidate content instead of calling twice.
throw;
} Prevention
- Define each Decoration layer (Before/Content/After) exactly once.
- Branch conditional content inside the single layer call, not by calling the layer twice.
- Audit all calls to .Before(/.Content(/.After( on the same instance.
When it happens
Trigger: Invoking .Before() twice on the same Decoration container, or calling both .Before() and .Before(handler) on it. The guard checks whether Decoration.Before is anything other than Empty/DebugPointer.
Common situations: Conditional code paths that both call Before; refactoring that merged two setup blocks; copy-paste of a header definition; framework code plus user code both writing Before.
Related errors
- The 'Decoration.Content' layer has already been defined. Ple
- The 'Decoration.After' layer has already been defined. Pleas
- {prefix} A cell must span at least one row. Got {cell.RowSpa
- {prefix} Cell starts at column that does not exist. Cell det
- {prefix} Table cell location is incorrect. Cell spans over c
AI-assisted analysis of QuestPDF/QuestPDF@43ab125596 (2026-08-13).
Data as JSON: /api/errors/6a49e1c29f2777fd.
Report an issue: GitHub.