Skip to content

Reference Lint Rules

Lint and validation rules ​

Run sprocket explain <RULE> for one rule or sprocket explain --tag <TAG> for every lint rule with a tag. Disable selected rules with configuration or lint directives; see Exceptions.

Rules from wdl-lint are listed as Lint rules. Rules from wdl-analysis are listed as Validation rules. Validation rules do not expose lint tags.

Summary ​

RuleKindTagsDescription
BashSetSyntaxLintCorrectnessEnsures that all command sections start with a valid set command.
CallInputKeywordLintStyle, DeprecatedEnsures that the input: keyword is not used in call statements when WDL version is 1.2 or later.
CommandSectionIndentationValidation—Ensures consistent indentation (no mixed spaces/tabs) within command sections.
ConciseInputLintStyleEnsures concise input assignments are used (implicit binding when available).
ContainerUriLintClarity, PortabilityEnsures that values for the container key within runtime/requirements sections are well-formed.
DeclarationNameLintNaming, Style, ClarityEnsures declaration names do not redundantly include their type name.
DenyGlobStarLintClarity, CorrectnessEnsures glob("*") is not used in output declarations.
DeprecatedObjectValidation—Ensures that the deprecated Object types are not used.
DeprecatedPlaceholderValidation—Ensures that deprecated expression placeholder options are not used.
DeprecatedRuntimeSectionValidation—Detects deprecated runtime sections.
DescriptionLengthLintSprocketCompatibilityEnsures that description meta entries are not too long for display in Sprocket documentation.
DocCommentTabsLintStyle, ClarityEnsures that doc comments do not contain tab characters.
DocMetaStringsLintSprocketCompatibilityEnsures that reserved meta keys have string values.
EmptyDocCommentLintClarity, DocumentationEnsures that documentation comment blocks are not empty.
EmptyOutputsLintCompletenessEnsures tasks specify an output section.
ExceptDirectiveValidValidation—Ensures except directives are placed correctly to have the intended effect.
ExpectedRuntimeKeysLintCompleteness, DeprecatedEnsures that runtime sections have the appropriate keys.
HereDocCommandsLintClarity, CorrectnessEnsures that tasks use heredoc syntax in command sections.
HostPathLiteralsLintPortabilityFlags File/Directory declaration defaults that use absolute host paths.
ImportPlacementLintClarityEnsures that imports are placed between the version statement and any document items.
InlineInstallLintPortability, Correctness, PerformanceEnsures inline installation of packages is not used in command sections.
InputNameLintNaming, StyleEnsures input names are meaningful (e.g. not generic like 'input', 'in', or too short).
KnownRulesValidation—Ensures only known rules are used in except directives.
MatchingOutputMetaLintCompleteness, Documentation, SprocketCompatibilityEnsures that each output field is documented in the meta section under meta.outputs.
MeaninglessLintDirectiveValidation—Warns if an #@ except: comment doesn't actually suppress a lint.
MetaDescriptionLintCompleteness, Documentation, SprocketCompatibilityEnsures the meta section contains a description key.
MetaSectionsLintCompleteness, Clarity, DocumentationEnsures that tasks and workflows have the required meta and parameter_meta sections, or supplementary doc comments.
MisleadingDeclarationOrderValidation—Warns when a variable declaration is placed after a command block.
OutputNameLintNaming, StyleEnsures output names are meaningful (e.g. not generic like 'output', 'out', or too short).
ParameterDescriptionLintCompleteness, DocumentationEnsures that parameters and outputs have proper descriptions.
ParameterMetaMatchedLintCompleteness, Sorting, Documentation, SprocketCompatibilityEnsures that inputs have a matching entry in a parameter_meta section.
PascalCaseLintNaming, Style, ClarityEnsures that structs are defined with PascalCase names.
RedundantNoneLintStyleFlags redundant assignment of None to optional inputs.
RequirementsSectionLintCompleteness, PortabilityEnsures that tasks have a requirements section (for WDL v1.2 and beyond).
RuntimeSectionLintCompleteness, PortabilityEnsures that tasks have a runtime section (for WDL v1.1 and prior).
ShellCheckLintCorrectnessEnsures that command blocks are free of ShellCheck violations.
SnakeCaseLintNaming, Style, ClarityEnsures that tasks, workflows, and variables are defined with snake_case names.
TodoCommentLintStyleFlags TODO statements in comments to ensure they are not forgotten.
UnnecessaryFunctionCallValidation—Ensures that function calls are necessary.
UnusedCallValidation—Ensures that outputs of a call statement are used in the declaring workflow.
UnusedDeclarationValidation—Ensures that private declarations in tasks or workspaces are used within the declaring task or workspace.
UnusedDocCommentsLintDocumentationReports doc comments that are attached to WDL items that don't support them.
UnusedImportValidation—Ensures that import namespaces are used in the importing document.
UnusedInputValidation—Ensures that task or workspace inputs are used within the declaring task or workspace.
UsingFallbackVersionValidation—Warns if interpretation of a document with an unsupported version falls back to a default.

Tags ​

Definitions ​

WDL Document Structure ​

Preamble ​

The document preamble is defined as anything before the version declaration statement and the version declaration statement itself. Only comments and whitespace are permitted before the version declaration.

Comment Types ​

Lint Directives ​

Lint directives are special comments that begin with #@ except: followed by a comma-delimited list of rule IDs. These comments are used to disable specific lint rules for a section of the document. When a lint directive is encountered in the preamble, it will disable the specified rules for the entire document.

For example:

wdl
#@ except: DoubleQuotes, ConciseInput

Preamble Comments ​

Preamble comments are special comments at the start of a WDL file that begin with double pound signs (##). These comments are used for documentation that doesn't fit within any of the WDL-defined documentation elements (i.e., meta and parameter_meta sections). They may provide context for a collection of tasks or structs, or they may provide a high-level overview of a workflow. Preamble comments can be formatted as Markdown text.

For example:

wdl
## # FlagFilter
##
## A struct to represent the filtering flags used in various `samtools` commands.

BashSetSyntax ​

  • Kind: Lint
  • Tags: Correctness

Ensures that all command sections start with a valid set command.

Bash has many silent failure cases, which can produce invalid results and be difficult to debug. The set command should be used in all command sections to enforce stricter behavior.

Configuration ​

bash_set_options ​

  • Default: ["errexit","nounset","pipefail"]

List of options to enforce in the bash set builtin for every command section.

Example ​
toml
 bash_set_options = ["errexit", "nounset", "pipefail"]

Examples ​

Problem

wdl
version 1.3

task say_hello {
    command <<<
        echo "Hello, World!"
    >>>
}

Assuming the default configuration

wdl
version 1.2

task say_hello {
    command <<<
        set -euo pipefail
        echo "Hello, World!"
    >>>
}

CallInputKeyword ​

  • Kind: Lint
  • Tags: Style, Deprecated

Ensures that the input: keyword is not used in call statements when WDL version is 1.2 or later.

Starting with WDL version 1.2, the input: keyword in call statements is optional. This specification change allows call inputs to be specified directly within the braces without the input: keyword, resulting in a cleaner and more concise syntax. This rule encourages adoption of the newer syntax when using WDL 1.2 or later.

Examples ​

Problem

wdl
version 1.2

workflow example {
    # In versions prior to WDL v1.2, the `input:` keyword
    # was necessary in `call` statements.
    call say_hello { input:
        name = "world",
    }
}

Revision

wdl
version 1.2

workflow example {
    # This is correct for WDL v1.2 and later.
    call say_hello {
        name = "world",
    }
}

CommandSectionIndentation ​

  • Kind: Validation
  • Tags: None

Ensures consistent indentation (no mixed spaces/tabs) within command sections.

Mixing indentation (tab and space) characters within the command line causes leading whitespace stripping to be skipped. Commands may be whitespace sensitive, and skipping the whitespace stripping step may cause unexpected behavior.

Examples ​

Problem

wdl
version 1.3

task say_greetings {
    input {
        String name
    }

    command <<<
        # this line is prefixed with tabs
		echo "Hello, ~{name}!"
        # this line is prefixed with spaces
        echo "Goodbye, ~{name}!"
    >>>
}

Revision

wdl
version 1.3

task say_greetings {
    input {
        String name
    }

    command <<<
        # this line is prefixed with spaces
        echo "Hello, ~{name}!"
        # this line is prefixed with spaces
        echo "Goodbye, ~{name}!"
    >>>
}

ConciseInput ​

  • Kind: Lint
  • Tags: Style

Ensures concise input assignments are used (implicit binding when available).

Redundant input assignments can be shortened in WDL versions >=v1.1 with an implicit binding. For example, { input: a = a } can be shortened to { input: a }.

Examples ​

Problem

wdl
version 1.2

workflow hello {
    input {
        String name
    }

    # Since WDL v1.1, these explicit bindings can be shortened.
    call say_hello {
        name = name,
    }
}

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

Revision

wdl
version 1.2

workflow hello {
    input {
        String name
    }

    # `name` can be passed in directly
    call say_hello {
        name,
    }
}

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

ContainerUri ​

  • Kind: Lint
  • Tags: Clarity, Portability

Ensures that values for the container key within runtime/requirements sections are well-formed.

This rule checks the following:

  • Containers should have a tag, as container URIs with no tags have no expectation that the behavior of the containers won't change between runs.
  • Further, immutable containers tagged with SHA256 sums are preferred. This is due to the requirement from the WDL specification that tasks produce functionally equivalent output across runs. When a mutable tag is used, there is a risk that changes to the container will cause different behavior between runs.
  • Use of the 'any' container URI (*) within an array of container URIs is ambiguous and should be avoided.
  • Empty container URI arrays are not disallowed by the specification but are ambiguous and should be avoided.
  • An array of container URIs with a single element should be changed to a single string value.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    # No tag
    requirements {
        container: "ubuntu"
    }
}

task say_goodbye {
    input {
        String name
    }

    command <<<
        echo "Goodbye, ~{name}!"
    >>>

    # Unnecessary array
    requirements {
        container: [
            "ubuntu@sha256:cc925e589b7543b910fea57a240468940003fbfc0515245a495dd0ad8fe7cef1",
        ]
    }
}

Revision

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    requirements {
        container: "ubuntu@sha256:cc925e589b7543b910fea57a240468940003fbfc0515245a495dd0ad8fe7cef1"
    }
}

task say_goodbye {
    input {
        String name
    }

    command <<<
        echo "Goodbye, ~{name}!"
    >>>

    requirements {
        container: "ubuntu@sha256:cc925e589b7543b910fea57a240468940003fbfc0515245a495dd0ad8fe7cef1"
    }
}

DeclarationName ​

Ensures declaration names do not redundantly include their type name.

Declaration names should not include their type. This makes the code more verbose and often redundant. For example, use 'counter' instead of 'counter_int' or 'is_active' instead of 'is_active_bool'. Exceptions are made for String, File, and user-defined struct types, which are not flagged by this rule.

Configuration ​

allowed_names ​

  • Default: []

List of names to ignore in the SnakeCase and DeclarationName lints.

Example ​
toml
 allowed_names = ["Foo", "counter_int"]

Examples ​

Problem

wdl
version 1.2

task example {
    input {
        Int total_count_int
    }
}

Revision

wdl
version 1.2

task example {
    input {
        Int total_count
    }
}

DenyGlobStar ​

  • Kind: Lint
  • Tags: Clarity, Correctness

Ensures glob("*") is not used in output declarations.

glob("*") captures all files; as a task grows, you may include unintended files and cause unnecessary aggregation. Prefer explicit patterns to opt in only to the files you need, keeping tasks easier to debug/reproduce.

Examples ​

Problem

wdl
version 1.2

task generate_files {
    command <<<
        touch foo.txt
        touch bar.txt
    >>>

    output {
        Array[File] files = glob("*")
    }
}

Revision

wdl
version 1.2

task generate_files {
    command <<<
        touch foo.txt
        touch bar.txt
    >>>

    output {
        # Specifically collect the .txt files
        Array[File] files = glob("*.txt")
    }
}

DeprecatedObject ​

  • Kind: Validation
  • Tags: None

Ensures that the deprecated Object types are not used.

WDL Object types are officially deprecated and will be removed in the next major WDL release.

Objects existed prior to better containers, such as Maps and Structs, being introduced into the language. Unfortunately, though these better alternatives did exist at the time of the v1.0 release, the type was not removed. It was later decided that Objects overlapped with Maps and Structs in functionality, and the type was marked for removal.

See this issue for more details: https://github.com/openwdl/wdl/pull/228.

Examples ​

Problem

wdl
version 1.2

workflow example {
    Object person = object {
        name: "Jimmy",
        age: 55,
    }
}

Consider switching to a Struct or Map

wdl
version 1.2

struct Person {
    String name
    Int age
}

workflow example {
    Person person = Person {
        name: "Jimmy",
        age: 55,
    }
}

DeprecatedPlaceholder ​

  • Kind: Validation
  • Tags: None

Ensures that deprecated expression placeholder options are not used.

Expression placeholder options were deprecated in WDL v1.1 and will be removed in the next major WDL version.

  • sep placeholder options should be replaced by the sep() standard library function.
  • true/false placeholder options should be replaced with if/else statements.
  • default placeholder options should be replaced by the select_first() standard library function.
  • ${} interpolation placeholders should be replaced by ~{} interpolation placeholders.

This rule only evaluates for WDL V1 documents with a version of v1.1 or later, as this was the version where the deprecation was introduced.

Examples ​

Problem

wdl
version 1.2

workflow example {
    Array[String] names = [
        "James",
        "Jimmy",
        "John",
    ]
    String names_separated = "~{sep="," names}"
    String names_interpolated = "${names_separated}"
}

Revision

wdl
version 1.2

workflow example {
    Array[String] names = [
        "James",
        "Jimmy",
        "John",
    ]
    String names_separated = "~{sep(",", names)}"
    String names_interpolated = "~{names_separated}"
}

DeprecatedRuntimeSection ​

  • Kind: Validation
  • Tags: None

Detects deprecated runtime sections.

The runtime section is deprecated in WDL v1.2 and later. Replace it with a requirements section.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    runtime {
        container: "ubuntu:latest"
    }
}

Revision

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    requirements {
        container: "ubuntu:latest"
    }
}

DescriptionLength ​

  • Kind: Lint
  • Tags: SprocketCompatibility

Ensures that description meta entries are not too long for display in Sprocket documentation.

Descriptions should be kept short so that they can always render in full. If a description is too long, it will be clipped in some documentation contexts. help meta entries are never clipped and may be a better place for long form text.

Examples ​

Problem

wdl
version 1.2

workflow example {
    meta {
        description: "This is an example workflow. It is very important for documentation purposes, as it conveys a real workflow document without having to provide any implementation."
    }
}

Revision

wdl
version 1.2

workflow example {
    meta {
        description: "This is an example workflow."
        # The `help` key can be used for extended descriptions
        help: "It is very important for documentation purposes, as it conveys a real workflow document without having to provide any implementation."
    }
}

DocCommentTabs ​

  • Kind: Lint
  • Tags: Style, Clarity

Ensures that doc comments do not contain tab characters.

Tabs render with different widths depending on the viewer. Doc comments should use spaces instead of tabs to ensure consistent rendering.

Examples ​

Problem

wdl
version 1.3

# Using tabs for alignment

##  {
##		"foo": 123,
##		^^^^^
##	}
workflow example {
    meta {
        description: 123
    }
}

Revision

wdl
version 1.3

# Using spaces for alignment

## {
##     "foo": 123,
##     ^^^^^
## }
workflow example {
    meta {
        description: "123"
    }
}

DocMetaStrings ​

Ensures that reserved meta keys have string values.

Sprocket's documentation command reserves certain keys in meta and parameter_meta sections for documentation generation. These keys (description, help, external_help, warning, category, and group) must have String values. Using non-String values will cause the documentation to be rendered incorrectly or not at all. This rule ensures all reserved keys have String values for proper documentation generation.

Examples ​

Problem

wdl
version 1.2

workflow example {
    meta {
        description: 123
    }
}

Revision

wdl
version 1.2

workflow example {
    meta {
        description: "123"
    }
}

EmptyDocComment ​

Ensures that documentation comment blocks are not empty.

Documentation comment blocks (consecutive lines starting with ##) where all lines are empty serve no purpose. Either add meaningful text to the documentation comment block or remove it entirely.

Examples ​

Problem

wdl
version 1.2

# This will render nothing!

##
struct Person {
    String name
    Int age
}

EmptyOutputs ​

  • Kind: Lint
  • Tags: Completeness

Ensures tasks specify an output section.

A task without an output section may be a mistake. This lint may be overzealous, as there are some legitimate use cases for tasks without outputs (e.g. uploading to an external service). In that case, authors should suppress the diagnostic on that specific task, and document its behavior in the meta section.

Examples ​

Problem

wdl
version 1.2

task generate_files {
    command <<<
        touch foo.txt
    >>>
}

If the results are intended to be received by the caller

wdl
version 1.2

task generate_files {
    command <<<
        touch foo.txt
    >>>

    output {
        File files = "foo.txt"
    }
}

ExceptDirectiveValid ​

  • Kind: Validation
  • Tags: None

Ensures except directives are placed correctly to have the intended effect.

When writing WDL, except directives are used to suppress certain rules. If an except directive is misplaced, it will have no effect. This rule flags misplaced except directives to ensure they are in the correct location.

Examples ​

Problem

wdl
version 1.3

# UsingFallbackVersion exceptions aren't valid
# in this context
#@ except: UsingFallbackVersion
workflow example {
}

Revision

wdl
#@ except: UsingFallbackVersion
version 1.3

workflow example {
}

ExpectedRuntimeKeys ​

Ensures that runtime sections have the appropriate keys.

The behavior of this rule is different depending on the WDL version:

For WDL v1.0 documents, the docker and memory keys are recommended, but the inclusion of any number of other keys is permitted.

For WDL v1.1 documents:

  • A list of mandatory, reserved keywords will be recommended for inclusion if they are not present. Here, 'mandatory' refers to the requirement that all execution engines support this key—not that the key must be present in the runtime section.
  • Optional, reserved "hint" keys are also permitted but not flagged when they are missing (as their support in execution engines is not guaranteed).
  • The WDL v1.1 specification deprecates the inclusion of non-reserved keys in a runtime section. As such, any non-reserved keys will be flagged for removal.

For WDL v1.2 documents and later, this rule does not evaluate because runtime sections were deprecated in this version.

Configuration ​

allowed_runtime_keys ​

  • Default: []

List of keys to ignore in the ExpectedRuntimeKeys lint.

Example ​
toml
 allowed_runtime_keys = ["foo"]

Examples ​

Example 1 ​

The following is missing a mandatory key

wdl
version 1.1

task missing_required_keys {
    runtime {
    # Missing `container` key
    }
}

Example 2 ​

The following has an unexpected key

wdl
version 1.1

task unexpected_runtime_key {
    runtime {
        container: "ubuntu"
        foo: "bar"
    }
}

HereDocCommands ​

  • Kind: Lint
  • Tags: Clarity, Correctness

Ensures that tasks use heredoc syntax in command sections.

Curly command blocks are no longer considered idiomatic WDL. Idiomatic WDL code uses heredoc command blocks instead. This is because curly command blocks create ambiguity with Bash syntax.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    command {
        echo "Hello, World!"
    }
}

Revision

wdl
version 1.2

task say_hello {
    command <<<
        echo "Hello, World!"
    >>>
}

HostPathLiterals ​

  • Kind: Lint
  • Tags: Portability

Flags File/Directory declaration defaults that use absolute host paths.

File and Directory declarations with absolute path defaults are not portable across environments. Use relative paths or supply values at runtime.

Examples ​

Problem

wdl
version 1.3

task run_tool {
    input {
        File data = "/etc/host/input.txt"
    }

    command <<<
        echo "run"
    >>>
}

ImportPlacement ​

  • Kind: Lint
  • Tags: Clarity

Ensures that imports are placed between the version statement and any document items.

All import statements should follow the WDL version declaration with one empty line between the version and the first import statement.

Examples ​

Problem

wdl
version 1.2

workflow example {
}

import "example2.wdl"

Revision

wdl
version 1.2

import "example2.wdl"

workflow example {
}

InlineInstall ​

  • Kind: Lint
  • Tags: Portability, Correctness, Performance

Ensures inline installation of packages is not used in command sections.

All required software should be installed in the execution environment before the workflow is run. Inline installations can lead to lack of reproducibility, portability, and incur a performance cost, as software must be downloaded and installed every invocation.

Examples ​

Problem

wdl
version 1.3

task say_hello {
    command <<<
        sudo apt install python3

        python3 -c "print('Hello, world!')"
    >>>

    requirements {
        container: "debian:trixie"
    }
}

Consider using a dedicated container image

wdl
version 1.3

task say_hello {
    command <<<
        python3 -c "print('Hello, world!')"
    >>>

    requirements {
        container: "python:trixie"
    }
}

InputName ​

Ensures input names are meaningful (e.g. not generic like 'input', 'in', or too short).

Any input name matching these regular expressions will be flagged: /^[iI]n[A-Z_]/, /^input/i or /^..?$/.

It is redundant and needlessly verbose to use an input's name to specify that it is an input. Input names should be short yet descriptive. Prefixing a name with in or input adds length to the name without adding clarity or context. Additionally, names with only 2 characters can lead to confusion and obfuscates the content of an input. Input names should be at least 3 characters long.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    input {
        String input_name
    }

    command <<<
        echo "Hello, ~{input_name}!"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    meta {
        description: "Says hello for the given name"
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

KnownRules ​

  • Kind: Validation
  • Tags: None

Ensures only known rules are used in except directives.

When writing WDL, except directives are used to suppress certain rules. If a rule is unknown, nothing will be suppressed. This rule flags unknown rules as they are often mistakes.

Examples ​

Problem

wdl
#@ except: LintThatDoesNotExist
version 1.2

workflow example {
}

Revision

wdl
version 1.2

workflow example {
}

MatchingOutputMeta ​

Ensures that each output field is documented in the meta section under meta.outputs.

The meta section should have an outputs key that is an object and contains keys with descriptions for each output of the task/workflow. These must match exactly. i.e. for each named output of a task or workflow, there should be an entry under meta.outputs with that same name. Additionally, these entries should be in the same order (that order is up to the developer to decide). No extraneous meta.outputs entries are allowed.

Examples ​

Problem

wdl
version 1.2

task generate_greeting {
    meta {
        outputs: {
        # Missing `greeting`
        }
    }

    input {
        String name
    }

    output {
        String greeting = "Hello, ~{name}!"
    }
}

Revision

wdl
version 1.2

task generate_greeting {
    meta {
        outputs: {
            greeting: "The generated greeting for the provided name",
        }
    }

    input {
        String name
    }

    output {
        String greeting = "Hello, ~{name}!"
    }
}

MeaninglessLintDirective ​

  • Kind: Validation
  • Tags: None

Warns if an #@ except: comment doesn't actually suppress a lint.

Unused #@ except: comments are likely leftovers of refactoring or debugging, and can reduce the clarity of the code. It is best to remove them.

Examples ​

Problem

wdl
version 1.3

task do_work {
    command <<<
        echo "Lots of hard work!"
    >>>

    output {
        String result = read_string(stdout())
    }
}

# We except `UnusedCall` unnecessarily.
workflow calculate {
    #@ except: UnusedCall
    call do_work

    output {
        # We're using the result here!
        String result = do_work.result
    }
}

Consider removing the unused exception

wdl
version 1.3

task do_work {
    command <<<
        echo "Lots of hard work!"
    >>>

    output {
        String result = read_string(stdout())
    }
}

workflow calculate {
    call do_work

    output {
        String result = do_work.result
    }
}

MetaDescription ​

Ensures the meta section contains a description key.

Each task, workflow, and struct should have a description in the meta section. The description should be short, written in active voice, and be in complete sentences. More detailed information can be included in the help key.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    meta {
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    meta {
        description: "Says hello for the given name"
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

MetaSections ​

Ensures that tasks and workflows have the required meta and parameter_meta sections, or supplementary doc comments.

It is important that WDL code is well-documented. Every task and workflow should be documented with both a meta and parameter_meta section, or doc comments. Tasks without an input section are permitted to skip the parameter_meta section.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    meta {
        description: "Says hello for the given name"
    }

    parameter_meta {
        name: "The name of the person to greet"
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

MisleadingDeclarationOrder ​

  • Kind: Validation
  • Tags: None

Warns when a variable declaration is placed after a command block.

WDL tasks are evaluated based on their dependency graph, not top-to-bottom. Variable declarations that appear after command sections are visually misleading, as they will still be evaluated before the command is executed.

Examples ​

Problem

wdl
version 1.2

task greet {
    String greeting = "Hello"

    command <<<
        echo "~{greeting}, ~{name}!"
    >>>

    String name = "World"
}

Revision

wdl
version 1.2

task greet {
    String greeting = "Hello"
    String name = "World"

    command <<<
        echo "~{greeting}, ~{name}!"
    >>>
}

OutputName ​

Ensures output names are meaningful (e.g. not generic like 'output', 'out', or too short).

Any output name matching these regular expressions will be flagged: /^[oO]ut[A-Z_]/, /^output/i or /^..?$/.

It is redundant and needlessly verbose to use an output's name to specify that it is an output. Output names should be short yet descriptive. Prefixing a name with out or output adds length to the name without adding clarity or context. Additionally, names with only 2 characters can lead to confusion and obfuscates the content of an output. Output names should be at least 3 characters long.

Examples ​

Problem

wdl
version 1.2

task generate_greeting {
    input {
        String name
    }

    command <<<
    >>>

    output {
        String output_greeting = "Hello, ~{name}!"
    }
}

Revision

wdl
version 1.2

task generate_greeting {
    input {
        String name
    }

    command <<<
    >>>

    output {
        String greeting = "Hello, ~{name}!"
    }
}

ParameterDescription ​

Ensures that parameters and outputs have proper descriptions.

Documentation is expected for each parameter (in parameter_meta) and each output (in meta.outputs). A valid description is either a simple String value or an object containing a description key with a String value.

Examples ​

Problem

wdl
version 1.2

task greet {
    meta {
        outputs: {
            greeting: {},
        }
    }

    parameter_meta {
        name: {}
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}"
    >>>

    output {
        String greeting = stdout()
    }
}

Revision

wdl
version 1.2

task greet {
    meta {
        outputs: {
            greeting: "The generated greeting message.",
        }
    }

    parameter_meta {
        name: "The name of the person to greet."
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}"
    >>>

    output {
        String greeting = stdout()
    }
}

ParameterMetaMatched ​

Ensures that inputs have a matching entry in a parameter_meta section.

Each input parameter within a task or workflow should have an associated parameter_meta entry with a detailed description of the input. Non-input keys are not permitted within the parameter_meta block.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    parameter_meta {
        name: "The name of the person to greet"
        does_not_exist: "This is not a real parameter"
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    parameter_meta {
        name: "The name of the person to greet"
    }

    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

PascalCase ​

  • Kind: Lint
  • Tags: Naming, Style, Clarity
  • Related rules: SnakeCase

Ensures that structs are defined with PascalCase names.

Struct names should be in PascalCase. Maintaining a consistent naming convention makes the code easier to read and understand.

Examples ​

Struct names should be in PascalCase

wdl
version 1.2

struct registered_user {
    String name
}

Revision

wdl
version 1.2

struct RegisteredUser {
    String name
}

RedundantNone ​

  • Kind: Lint
  • Tags: Style

Flags redundant assignment of None to optional inputs.

The specification states that an optional input declaration (e.g., String? foo) is implicitly initialized to None if no default is provided. Therefore explicitly writing String? foo = None is equivalent to String? foo but adds unnecessary verbosity.

Examples ​

Problem

wdl
version 1.2

workflow example {
    input {
        String? name = None
    }
}

Revision

wdl
version 1.2

workflow example {
    input {
        String? name
    }
}

RequirementsSection ​

Ensures that tasks have a requirements section (for WDL v1.2 and beyond).

Tasks that don't declare requirements sections are unlikely to be portable.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    requirements {
        container: "ubuntu:latest"
    }
}

RuntimeSection ​

Ensures that tasks have a runtime section (for WDL v1.1 and prior).

Tasks that don't declare runtime sections are unlikely to be portable.

Examples ​

Problem

wdl
version 1.1

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>
}

Revision

wdl
version 1.1

task say_hello {
    input {
        String name
    }

    command <<<
        echo "Hello, ~{name}!"
    >>>

    runtime {
        container: "ubuntu:latest"
    }
}

ShellCheck ​

  • Kind: Lint
  • Tags: Correctness

Ensures that command blocks are free of ShellCheck violations.

ShellCheck is a static analysis tool and linter for sh / bash. The lints provided by ShellCheck help prevent common errors and pitfalls in your scripts. Following its recommendations will increase the robustness of your command sections.

Examples ​

Problem

wdl
version 1.2

task say_hello {
    # Triggers SC2154
    command <<<
        echo "Hello $name"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    command <<<
        name=World
        echo "Hello $name"
    >>>
}

SnakeCase ​

  • Kind: Lint
  • Tags: Naming, Style, Clarity
  • Related rules: PascalCase

Ensures that tasks, workflows, and variables are defined with snake_case names.

Workflow, task, and variable names should be in snake case. Maintaining a consistent naming convention makes the code easier to read and understand.

Configuration ​

allowed_names ​

  • Default: []

List of names to ignore in the SnakeCase and DeclarationName lints.

Example ​
toml
 allowed_names = ["Foo", "counter_int"]

Examples ​

Problem

wdl
version 1.2

task SayHello {
    command <<<
        echo "Hello, World!"
    >>>
}

Revision

wdl
version 1.2

task say_hello {
    command <<<
        echo "Hello, World!"
    >>>
}

TodoComment ​

  • Kind: Lint
  • Tags: Style

Flags TODO statements in comments to ensure they are not forgotten.

When writing WDL, future tasks are often marked as TODO. This indicates that the implementor intended to go back to the code and handle the todo item. TODO items should not be long-term fixtures within code and, as such, they are flagged to ensure none are forgotten.

Examples ​

The following comment will be flagged

wdl
version 1.2

# TODO: Implement this workflow
workflow example {
    meta {
    }

    output {
    }
}

UnnecessaryFunctionCall ​

  • Kind: Validation
  • Tags: None

Ensures that function calls are necessary.

Unnecessary function calls may impact evaluation performance.

Examples ​

Problem

wdl
version 1.2

workflow example {
    # Calls to `defined` on values that are statically
    # known to be non-None are unnecessary.
    Boolean exists = defined("hello")
}

UnusedCall ​

  • Kind: Validation
  • Tags: None

Ensures that outputs of a call statement are used in the declaring workflow.

Unused calls may cause unnecessary consumption of compute resources.

Examples ​

Problem

wdl
version 1.2

workflow example {
    # The output of `do_work` is never used
    call do_work
}

task do_work {
    command <<<
    >>>

    output {
        Int x = 0
    }
}

Consider removing the call entirely

wdl
version 1.2

workflow example {
}

task do_work {
    command <<<
    >>>

    output {
        Int x = 0
    }
}

UnusedDeclaration ​

  • Kind: Validation
  • Tags: None

Ensures that private declarations in tasks or workspaces are used within the declaring task or workspace.

Unused private declarations degrade evaluation performance and reduce the clarity of the code.

Examples ​

Problem

wdl
version 1.2

workflow example {
    String unused = "this will produce a warning"
}

Consider removing the declaration entirely

wdl
version 1.2

workflow example {
}

UnusedDocComments ​

  • Kind: Lint
  • Tags: Documentation

Reports doc comments that are attached to WDL items that don't support them.

Some Workflow Definition Language items do not support doc comments (##). This lint reports if a doc comment is attached to an item that isn't supported.

Doc comments are supported on:

  • Workflow Definitions
  • Task Definitions
  • Struct Definitions
  • Fields in Struct Definitions
  • Fields in Input Sections
  • Fields in Output Sections
  • Enum Definitions
  • Enum Choices

Examples ​

Problem

wdl
version 1.2

workflow example {
    # This isn't documenting anything!
    ## The inputs for the workflow
    input {
        String name
    }

    # Neither is this!
    ## The outputs for the workflow
    output {
        String greeting = "Hello, ~{name}!"
    }
}

Consider removing the comments or moving them to applicable items

wdl
version 1.2

workflow example {
    input {
        ## The name to greet
        String name
    }

    output {
        ## The generated greeting
        String greeting = "Hello, ~{name}!"
    }
}

UnusedImport ​

  • Kind: Validation
  • Tags: None

Ensures that import namespaces are used in the importing document.

Imported WDL documents should be used in the document that imports them. Unused imports impact parsing and evaluation performance.

Examples ​

Problem

wdl
version 1.3

import "bar.wdl"
import "foo.wdl" as used

workflow example {
    call used.test
}

Consider removing the import entirely

wdl
version 1.3

import "foo.wdl" as used

workflow example {
    call used.test
}

UnusedInput ​

  • Kind: Validation
  • Tags: None

Ensures that task or workspace inputs are used within the declaring task or workspace.

Unused inputs degrade evaluation performance and reduce the clarity of the code. Unused file inputs in tasks can also cause unnecessary file localizations.

Examples ​

Problem

wdl
version 1.2

workflow example {
    input {
        String unused
    }
}

Consider removing the input entirely

wdl
version 1.2

workflow example {
    input {
    }
}

UsingFallbackVersion ​

  • Kind: Validation
  • Tags: None

Warns if interpretation of a document with an unsupported version falls back to a default.

A document with an unsupported version may have unpredictable behavior if interpreted as a different version.

Examples ​

Problem

wdl
# Not a valid version. If a fallback version is configured,
# the document will be interpreted as that version.
version development

workflow example {
}

Search commands, configuration, and guides.