realm / realm/SwiftLint

swiftlint crashes due to duplicate keys in configuration

Open
#6,052 4 comments 2 reactions 1 assignee View on GitHub

@mildm8nnered is already working on this.

Since Apr 24, 2025.

bug
Dominant language
Swift
Stars
19.7k
Forks
2.3k
Avg merge
1d 1h
Merged PRs (30d)
11

Description

New Issue Checklist
Bug Description

Swiftlint crashes while trying to read .swiftlint.yml with duplicating keys in sub-directory.

$ find .
.
./subdir
./subdir/.swiftlint.yml
./subdir/a.swift
$ cat subdir/.swiftlint.yml 
opt_in_rules:
  - closure_body_length

opt_in_rules:
  - closure_body_length
$ ~/GitHub/SwiftLint/.build/debug/swiftlint
Linting Swift files in current working directory
The operation couldn’t be completed. (SwiftLintCore.Issue error 15.)
Could not read configuration: file Configuration.swift, line 289
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Abort trap: 6 (core dumped)
$ ~/GitHub/SwiftLint/.build/debug/swiftlint --version
0.59.0

If I run swiftlint in subdirectory it correctly reports an error:

$ cd subdir/
$ ~/GitHub/SwiftLint/.build/debug/swiftlint 
warning: Cannot parse YAML file: error: parser: expected all keys to be unique but found the following duplicated key(s):
opt_in_rules ([1:1, 4:1]):
opt_in_rules:
^
opt_in_rules:
^ – Falling back to default configuration
Linting Swift files in current working directory
Linting 'a.swift' (1/1)
Done linting! Found 0 violations, 0 serious in 1 file.

Stacktrace:

thread #2
    frame #0: 0x000000018e4f0388 libsystem_kernel.dylib`__pthread_kill + 8
    frame #1: 0x000000018e52988c libsystem_pthread.dylib`pthread_kill + 296
    frame #2: 0x000000018e432cf0 libsystem_c.dylib`__abort + 132
    frame #3: 0x000000018e432c6c libsystem_c.dylib`abort + 136
    frame #4: 0x000000010312be78 swiftlint`queuedFatalError(string="Could not read configuration", file="SwiftLintFramework/Configuration.swift", line=289) at QueuedPrint.swift:61:5
    frame #5: 0x00000001031ba218 swiftlint`Configuration.init(configurationFiles=1 value, enableAllRules=false, onlyRule=0 values, cachePath=nil, ignoreParentAndChildConfigs=true, mockedNetworkResults=0 key/value pairs, useDefaultConfigOnFailure=nil) at Configuration.swift:289:17
    frame #6: 0x00000001031a1148 swiftlint`Configuration.configuration(directory=Swift.String @ 0x000000016d5ec730) at Configuration+Merging.swift:117:38
    frame #7: 0x00000001031a0c70 swiftlint`implicit closure #2 in implicit closure #1 in Configuration.configuration() at Configuration+Merging.swift:88:61
    frame #8: 0x00000001031a177c swiftlint`thunk for @callee_guaranteed (@guaranteed String) -> (@owned Configuration) at <compiler-generated>:0
    frame #9: 0x00000001031a17c4 swiftlint`partial apply for thunk for @callee_guaranteed (@guaranteed String) -> (@owned Configuration) at <compiler-generated>:0
    frame #10: 0x00000001028c1704 swiftlint`Optional.map<String, B>(_:) at <compiler-generated>:0
    frame #11: 0x00000001031a0a94 swiftlint`Configuration.configuration(file=0x00006000019a41e0) at Configuration+Merging.swift:88:57
    frame #12: 0x000000010318c788 swiftlint`closure #1 in Configuration.groupFiles(file=0x00006000019a41e0) at Configuration+CommandLine.swift:115:37
    frame #13: 0x00000001030f2e64 swiftlint`Array.filterGroup<SwiftLintCore.SwiftLintFile>(transform=0x1031902bc) at Array+SwiftLint.swift:76:26
    frame #14: 0x00000001030f3698 swiftlint`Array.parallelFilterGroup<SwiftLintCore.SwiftLintFile>(transform=0x1031902bc) at Array+SwiftLint.swift:93:20
    frame #15: 0x0000000103188f20 swiftlint`Configuration.groupFiles(files=1 value, visitor=SwiftLintFramework.LintableFilesVisitor @ 0x0000000116827840) at Configuration+CommandLine.swift:114:22
    frame #16: 0x0000000103188b28 swiftlint`closure #2 in Configuration.visitLintableFiles(, files=1 value, visitor=SwiftLintFramework.LintableFilesVisitor @ 0x0000000116827840) at Configuration+CommandLine.swift:82:17
    frame #17: 0x0000000103188b98 swiftlint`partial apply for closure #2 in Configuration.visitLintableFiles(with:storage:) at <compiler-generated>:0
    frame #18: 0x00000001031fc5dc swiftlint`static Signposts.record<[SwiftLintFramework.Configuration : [SwiftLintCore.SwiftLintFile]]>(name="Configuration.VisitLintableFiles.GroupFiles", span=timeline, body=0x103188b78) at Signposts.swift:32:26
    frame #19: 0x0000000103186848 swiftlint`Configuration.visitLintableFiles(visitor=SwiftLintFramework.LintableFilesVisitor @ 0x0000000116833348, storage=0x00006000017bd740) at Configuration+CommandLine.swift:81:42
    frame #20: 0x0000000103190854 swiftlint`Configuration.visitLintableFiles(options=SwiftLintFramework.LintOrAnalyzeOptions @ 0x000000011681f840, cache=0x00006000039bc680, storage=0x00006000017bd740, visitorBlock=0x0000000104003b88 async function pointer to partial apply forwarder for closure #1 (SwiftLintFramework.CollectedLinter) async -> () in static SwiftLintFramework.LintOrAnalyzeCommand.collectViolations(builder: SwiftLintFramework.LintOrAnalyzeResultBuilder) async throws -> Swift.Array<SwiftLintCore.SwiftLintFile>) at Configuration+CommandLine.swift:293:26
    frame #21: 0x00000001031cd6a4 swiftlint`static LintOrAnalyzeCommand.collectViolations(builder=0x00000001371060a0) at LintOrAnalyzeCommand.swift:163:48
    frame #22: 0x00000001031cca3c swiftlint`static LintOrAnalyzeCommand.lintOrAnalyze(options=SwiftLintFramework.LintOrAnalyzeOptions @ 0x0000000137810620) at LintOrAnalyzeCommand.swift:144:31
    frame #23: 0x00000001031cbb70 swiftlint`closure #1 in static LintOrAnalyzeCommand.run(options=SwiftLintFramework.LintOrAnalyzeOptions @ 0x0000000137810620) at LintOrAnalyzeCommand.swift:138:68
    frame #24: 0x00000001031cbc78 swiftlint`partial apply for closure #1 in static LintOrAnalyzeCommand.run(_:) at <compiler-generated>:0
    frame #25: 0x00000001031fcea0 swiftlint`static Signposts.record<()>(name="LintOrAnalyzeCommand.run", span=timeline, body=0x104003b40) at Signposts.swift:63:32
    frame #26: 0x00000001031cb868 swiftlint`static LintOrAnalyzeCommand.run(options=SwiftLintFramework.LintOrAnalyzeOptions @ 0x0000000137810918) at LintOrAnalyzeCommand.swift:137:29
    frame #27: 0x0000000103c22afc swiftlint`SwiftLint.Lint.run() at Lint.swift:63:44
    frame #28: 0x0000000103c257f8 swiftlint`protocol witness for AsyncParsableCommand.run() in conformance SwiftLint.Lint at <compiler-generated>:0
    frame #29: 0x00000001028cb8cc swiftlint`static AsyncParsableCommand.main(arguments=nil) at AsyncParsableCommand.swift:41:32
    frame #30: 0x00000001028cbbf0 swiftlint`static AsyncParsableCommand.main() at AsyncParsableCommand.swift:61:16
    frame #31: 0x0000000103c412bc swiftlint`static SwiftLint.$main() at SwiftLint.swift:9:1
    frame #32: 0x0000000103c4182c swiftlint`async_MainTQ0_ at SwiftLint.swift:10:8
    frame #33: 0x0000000103c41950 swiftlint`thunk for @escaping @convention(thin) @async () -> () at <compiler-generated>:0
    frame #34: 0x0000000103c41a78 swiftlint`partial apply for thunk for @escaping @convention(thin) @async () -> () at <compiler-generated>:0

At least 0.57.0 doesn't crash, so looks like recent regression.
I tried to bisect but stuck due to:

$ git bisect good
Bisecting: 135 revisions left to test after this (roughly 7 steps)
[7421e24fc281d73d4c37550f95054751b4fc0f8f] Use action to extract binary from Docker image
$ swift build
Fetching https://github.com/ileitch/swift-filename-matcher
Updating https://github.com/jpsim/SourceKitten.git
Updating https://github.com/drmohundro/SWXMLHash.git
...
Downloading binary artifact https://github.com/realm/SwiftLint/releases/download/0.57.1/SwiftLintBinary.artifactbundle.zip
error: failed downloading 'https://github.com/realm/SwiftLint/releases/download/0.57.1/SwiftLintBinary.artifactbundle.zip' which is required by binary target 'SwiftLintBinary': badResponseStatusCode(404)
Environment
  • SwiftLint version (run swiftlint version to be sure)
    0.59.0

  • Installation method used (Homebrew, CocoaPods, building from source, etc)
    Built from source.

  • Configuration file:

opt_in_rules:
  - closure_body_length

opt_in_rules:
  - closure_body_length

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.