'Expressions are not allowed at the top level' if the module is not main.swift
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
This Swift error appears when executable statements are written directly in a file that is not acting as the program entry point. In older Swift project layouts, top-level code belongs in main.swift; in newer layouts, the entry point is often an @main type, but the rule is the same: only the program entry point can execute top-level expressions.
What counts as a top-level expression
A top-level expression is code written outside a type, function, or method body.
For example, this is top-level executable code:
If this appears in an ordinary source file inside a module, Swift complains because that file is not the designated program entry point.
Why main.swift used to matter so much
In a Swift executable target, main.swift was the conventional file where top-level statements were allowed. The compiler treated it as the startup file for the program.
So this works in main.swift:
But placing the same code into a regular file such as Helpers.swift causes the error, because Helpers.swift is supposed to define reusable declarations rather than perform startup work directly.
Modern fix: use @main
A clearer modern pattern is to define an explicit entry type:
Now the executable code is inside main(), and other files in the module can contain only declarations such as structs, classes, enums, extensions, and functions.
What to do in a non-entry file
If the code is currently in some other file, move the executable part into a function or type:
Then call that function from the actual entry point:
This keeps the module organized and matches how Swift expects source files to behave.
Common situations where the error appears
This error often appears when:
- copying sample code into a library file,
- moving code out of
main.swiftwithout wrapping it, - building code as a framework instead of an executable,
- or mixing script-style Swift code with a compiled module target.
Swift scripts are more permissive because the entire file behaves like an entry point. Compiled modules are stricter. That distinction is the real reason sample code copied from a playground or script can suddenly fail once it is moved into a project target.
Common Pitfalls
The biggest mistake is assuming every .swift file can behave like a script. In a module, ordinary files are for declarations, not standalone execution.
Another issue is fixing only one line and leaving several other executable statements at the top level. The error may reappear until all top-level expressions are moved into a valid entry point or declaration.
Be careful when migrating project structure too. A file that was valid in a quick command-line test may stop working once the code is moved into a framework or app target with a different entry model.
Finally, do not confuse variable declarations with harmless metadata. A constant declaration with an initializer can still count as top-level executable work in the wrong context if it participates in startup logic.
Summary
- Top-level executable expressions are allowed only in the program entry point.
- In older layouts that usually means
main.swift. - In modern Swift,
@mainis often the clearer solution. - Non-entry files should contain declarations, not standalone executable statements.
- Move startup code into
main()or a function called by the entry point.

