fix(platform): defer PlatformAPI resolution to prevent Linux segfault#3701
fix(platform): defer PlatformAPI resolution to prevent Linux segfault#3701enXov wants to merge 3 commits intospicetify:mainfrom
Conversation
…etify#3695) On Spotify 1.2.82 for Linux, eagerly calling all _platform.get*() native getters at startup triggers a SIGSEGV in Chromium's native layer. This change converts all PlatformAPI getters to lazy Object.defineProperty accessors that only invoke native code on first access. Changes: - spicetifyWrapper.js: Lazy getters for waitForPlatform() and addMissingPlatformAPIs() via Object.defineProperty with self-caching - homeConfig.js: Null check for Platform.History - expFeatures.js: Optional chaining for RemoteConfigDebugAPI - apply.go: Defensive typeof checks for expFeatureOverride, RemoteConfigResolver, and HomeConfig.arrange hooks Tested on Linux 1.2.82 — Spotify opens, Marketplace loads, no segfault. Backward-compatible with Windows/macOS (APIs resolve on first access).
|
No actionable comments were generated in the recent review. 🎉 📝 WalkthroughWalkthroughAdds lazy getters to Spicetify.Platform (including Registry-backed entries) that resolve and cache APIs on first access with error handling; adds runtime guards elsewhere to avoid startup native calls; introduces a comprehensive test suite validating lazy resolution, caching, enumeration, and failure modes. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/apply/apply.go (1)
481-486:⚠️ Potential issue | 🔴 CriticalFix unbalanced object literal in RemoteConfigResolver try/catch wrapper.
The replacement at line 484 generates invalid JavaScript due to incomplete brace matching. Submatches[4] captures
{value:{localConfiguration(two opening braces, zero closing), and the format string ends with%s}catch(_e){};. When combined, this produces:try{Spicetify.RemoteConfigResolver={value:{localConfiguration}catch(_e){};The single
}only closes{localConfiguration, leaving the outer{value:unclosed before the try block ends, resulting in a parse-time SyntaxError that breaks the entire xpui.js file.The fix is to add an extra closing brace:
Add closing brace for the outer object
- return fmt.Sprintf("%stry{Spicetify.createInternalMap=%s}catch(_e){};%stry{Spicetify.RemoteConfigResolver=%s}catch(_e){};{value:{localConfiguration", submatches[1], submatches[2], submatches[3], submatches[4]) + return fmt.Sprintf("%stry{Spicetify.createInternalMap=%s}catch(_e){};%stry{Spicetify.RemoteConfigResolver=%s}}catch(_e){};{value:{localConfiguration", submatches[1], submatches[2], submatches[3], submatches[4])This ensures both the assignment object and the try block are properly closed before the catch clause.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/apply/apply.go` around lines 481 - 486, The replacement using utils.ReplaceOnce that builds the fmt.Sprintf for wrapping Spicetify.RemoteConfigResolver produces an unbalanced object literal because submatches[4] includes "{value:{localConfiguration" (two opens) but the format string only supplies one closing brace; update the fmt.Sprintf format used in the anonymous function inside ReplaceOnce (the code that references submatches[1..4]) to add one more closing '}' before the "catch(_e){};" so the assigned object literal is fully closed (i.e., ensure the format string ends with "...%s}catch(_e){};}" or otherwise places an extra '}' to balance the outer "{value:{" captured in submatches[4]).
🧹 Nitpick comments (2)
jsHelper/__tests__/platformAPI.test.js (1)
1-30: Custom test harness is pragmatic but worth noting the trade-off.Since
spicetifyWrapper.jsrelies on browser globals (window, DOM), a Node.js-based test file that simulates the lazy getter logic (rather than importing it) is a reasonable approach. Be aware thatsimulateWaitForPlatform/simulateAddMissingPlatformAPIsduplicate the production code — if the logic inspicetifyWrapper.jschanges, these helpers must be updated in lockstep.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jsHelper/__tests__/platformAPI.test.js` around lines 1 - 30, The test file duplicates production logic for lazy PlatformAPI resolution (simulateWaitForPlatform and simulateAddMissingPlatformAPIs) which risks getting out of sync with spicetifyWrapper.js; instead, refactor the tests to import the real lazy-getter behavior from spicetifyWrapper.js or centralize the shared helper into a single test utility used by both code and tests. Update test harness to call the exported helper (or require a new test-utils module) so simulateWaitForPlatform and simulateAddMissingPlatformAPIs are removed from platformAPI.test.js and the test exercises the actual get/set behavior from spicetifyWrapper.js.jsHelper/spicetifyWrapper.js (1)
363-401: LGTM — Registry-based lazy getters with proper guards.The
Object.hasOwncheck correctly avoids overwriting APIs already resolved fromwaitForPlatform. The outer try/catch at line 399 handles unexpected iteration failures gracefully.One thing to note: if
Spicetify.Platform.versionis unavailable (line 356 fails), the function returns early without setting up Registry APIs. If there's a scenario whereRegistryis available butversionis not (or is malformed), this would silently skip all Registry-based resolution. Consider whether a version parse failure should prevent Registry resolution, or whether they should be independent.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jsHelper/spicetifyWrapper.js` around lines 363 - 401, The current flow bail-outs when Spicetify.Platform.version is missing or malformed which prevents setting up Registry-based lazy getters; update the logic so Spicetify.Platform.Registry handling is independent of Spicetify.Platform.version: remove or change the early return/path that depends on Spicetify.Platform.version (the code referencing Spicetify.Platform.version and the conditional that returns before the Registry loop) and instead only skip the Registry loop when Spicetify.Platform.Registry or Spicetify.Platform.Registry._map is absent; keep the existing guards around Spicetify.Platform.Registry and the try/catch in the Registry iteration so Registry resolution proceeds even if version parsing fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@jsHelper/__tests__/platformAPI.test.js`:
- Around line 145-152: Refactor the inline multi-statement arrow getters on the
_platform object (getPlayerAPI and getHistoryAPI) to match project formatting:
replace the compact inline arrow bodies with properly formatted function bodies
(either a named function expression or an arrow with a block and an explicit
return on its own line), ensuring consistent newlines and indentation so the
simulateWaitForPlatform(_platform) call and exported symbols (Platform,
getterCallLog) remain unchanged; this will satisfy the CI formatter while
preserving the callCount increment and returned objects.
---
Outside diff comments:
In `@src/apply/apply.go`:
- Around line 481-486: The replacement using utils.ReplaceOnce that builds the
fmt.Sprintf for wrapping Spicetify.RemoteConfigResolver produces an unbalanced
object literal because submatches[4] includes "{value:{localConfiguration" (two
opens) but the format string only supplies one closing brace; update the
fmt.Sprintf format used in the anonymous function inside ReplaceOnce (the code
that references submatches[1..4]) to add one more closing '}' before the
"catch(_e){};" so the assigned object literal is fully closed (i.e., ensure the
format string ends with "...%s}catch(_e){};}" or otherwise places an extra '}'
to balance the outer "{value:{" captured in submatches[4]).
---
Nitpick comments:
In `@jsHelper/__tests__/platformAPI.test.js`:
- Around line 1-30: The test file duplicates production logic for lazy
PlatformAPI resolution (simulateWaitForPlatform and
simulateAddMissingPlatformAPIs) which risks getting out of sync with
spicetifyWrapper.js; instead, refactor the tests to import the real lazy-getter
behavior from spicetifyWrapper.js or centralize the shared helper into a single
test utility used by both code and tests. Update test harness to call the
exported helper (or require a new test-utils module) so simulateWaitForPlatform
and simulateAddMissingPlatformAPIs are removed from platformAPI.test.js and the
test exercises the actual get/set behavior from spicetifyWrapper.js.
In `@jsHelper/spicetifyWrapper.js`:
- Around line 363-401: The current flow bail-outs when
Spicetify.Platform.version is missing or malformed which prevents setting up
Registry-based lazy getters; update the logic so Spicetify.Platform.Registry
handling is independent of Spicetify.Platform.version: remove or change the
early return/path that depends on Spicetify.Platform.version (the code
referencing Spicetify.Platform.version and the conditional that returns before
the Registry loop) and instead only skip the Registry loop when
Spicetify.Platform.Registry or Spicetify.Platform.Registry._map is absent; keep
the existing guards around Spicetify.Platform.Registry and the try/catch in the
Registry iteration so Registry resolution proceeds even if version parsing
fails.
- Format test file with biome (multi-line arrow functions) - Fix unbalanced braces in RemoteConfigResolver try-catch wrapper
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
jsHelper/__tests__/platformAPI.test.js (3)
15-35: Custom test harness is pragmatic but may be worth migrating to an established runner.The hand-rolled
test/describe/report functions work, but they lack features likebeforeEach, async support, and IDE integration that a lightweight runner (e.g.,node --testbuilt-in, available since Node 18) would provide for free. Not blocking, but worth considering as the test suite grows.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jsHelper/__tests__/platformAPI.test.js` around lines 15 - 35, Replace the custom test harness (functions test, describe and the counters testsPassed/testsFailed and failures) with a real test runner: remove the hand-rolled test/describe/report implementation and migrate tests to use the built-in Node test API (import { test, describe, beforeEach } from 'node:test') or another chosen runner (e.g., Jest); update each test case to use async functions where needed, replace manual assertions with assert from 'node:assert' or the runner's expect, and remove reliance on testsPassed/testsFailed/failures so the runner handles reporting and lifecycle hooks like beforeEach. Ensure any top-level describe/test calls are converted to the runner's APIs (refer to test and describe symbols) and that async tests return/promises are awaited.
41-78: Tests exercise duplicated simulation logic rather than the actualspicetifyWrapper.jsfunctions.
simulateWaitForPlatformandsimulateAddMissingPlatformAPIsre-implement the lazy-getter logic fromspicetifyWrapper.js(lines 316-326, 369-376). If the production code changes, these simulations can silently drift out of sync and give false-passing tests.Consider extracting the core lazy-getter wiring into importable helper functions in
spicetifyWrapper.js(or a shared module) and importing them here, so the tests exercise the real code path.Also applies to: 80-137
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jsHelper/__tests__/platformAPI.test.js` around lines 41 - 78, The tests reimplement the lazy-getter wiring (simulateWaitForPlatform / simulateAddMissingPlatformAPIs) which can drift from spicetifyWrapper.js; extract the shared lazy-getter logic into an exported helper function (e.g., createLazyGetters or wireLazyGetters) in spicetifyWrapper.js or a small shared module and update spicetifyWrapper.js to call that helper where it currently defines the getters; then update the tests to import and call this helper (preserving the getterCallLog behavior) instead of duplicating the implementation so tests exercise the real code path.
454-466: Consider printing the report and exiting unconditionally to avoid silent swallowing.If the test file is run in a CI pipeline,
process.exit(1)on failure is correct. However, if someone imports this file as a module (unlikely but possible), the top-levelprocess.exitwould terminate the parent process. A minor concern given the standalone design, but worth noting.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@jsHelper/__tests__/platformAPI.test.js` around lines 454 - 466, The test runner currently prints the summary and calls process.exit(...) unconditionally which can terminate a parent process if this file is imported; change it so the report printing always happens but the call to process.exit(testsFailed > 0 ? 1 : 0) is only executed when the file is run directly (use the standard check for module entry, e.g. require.main === module) or export a run function that returns the exit code instead of exiting; ensure you reference and use the existing symbols testsPassed, testsFailed, failures and only guard the process.exit call while keeping the failure reporting logic intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/apply/apply.go`:
- Line 485: The formatted JS string building the RemoteConfigResolver try-catch
is missing a closing brace: in the fmt.Sprintf that constructs the snippet
assigning Spicetify.RemoteConfigResolver (the line using submatches[1..4]),
change the sequence right before catch from "}}catch" to "}}}catch" so the
nested object literal and the try block are properly closed (i.e., ensure the
format string around Spicetify.RemoteConfigResolver ends with three closing
braces before "catch(_e){};").
---
Nitpick comments:
In `@jsHelper/__tests__/platformAPI.test.js`:
- Around line 15-35: Replace the custom test harness (functions test, describe
and the counters testsPassed/testsFailed and failures) with a real test runner:
remove the hand-rolled test/describe/report implementation and migrate tests to
use the built-in Node test API (import { test, describe, beforeEach } from
'node:test') or another chosen runner (e.g., Jest); update each test case to use
async functions where needed, replace manual assertions with assert from
'node:assert' or the runner's expect, and remove reliance on
testsPassed/testsFailed/failures so the runner handles reporting and lifecycle
hooks like beforeEach. Ensure any top-level describe/test calls are converted to
the runner's APIs (refer to test and describe symbols) and that async tests
return/promises are awaited.
- Around line 41-78: The tests reimplement the lazy-getter wiring
(simulateWaitForPlatform / simulateAddMissingPlatformAPIs) which can drift from
spicetifyWrapper.js; extract the shared lazy-getter logic into an exported
helper function (e.g., createLazyGetters or wireLazyGetters) in
spicetifyWrapper.js or a small shared module and update spicetifyWrapper.js to
call that helper where it currently defines the getters; then update the tests
to import and call this helper (preserving the getterCallLog behavior) instead
of duplicating the implementation so tests exercise the real code path.
- Around line 454-466: The test runner currently prints the summary and calls
process.exit(...) unconditionally which can terminate a parent process if this
file is imported; change it so the report printing always happens but the call
to process.exit(testsFailed > 0 ? 1 : 0) is only executed when the file is run
directly (use the standard check for module entry, e.g. require.main === module)
or export a run function that returns the exit code instead of exiting; ensure
you reference and use the existing symbols testsPassed, testsFailed, failures
and only guard the process.exit call while keeping the failure reporting logic
intact.
src/apply/apply.go
Outdated
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Get context around line 485 in src/apply/apply.go
sed -n '475,495p' src/apply/apply.go | cat -nRepository: spicetify/cli
Length of output: 985
🏁 Script executed:
#!/bin/bash
# Get the full insertExpFeatures function to understand context
rg -A 50 'func insertExpFeatures' src/apply/apply.go | head -100Repository: spicetify/cli
Length of output: 2152
🏁 Script executed:
#!/bin/bash
# Find the regex pattern used for this replacement
rg -B 5 'RemoteConfigResolver' src/apply/apply.go | grep -A 5 'regexp\|pattern'Repository: spicetify/cli
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check if there are test files that verify the output format
find . -type f -name '*test*.go' | xargs grep -l 'RemoteConfigResolver' 2>/dev/nullRepository: spicetify/cli
Length of output: 41
🏁 Script executed:
#!/bin/bash
# Search for test files related to apply functionality
find . -type f \( -name '*test.go' -o -name '*_test.go' \) | xargs grep -l 'insertExpFeatures\|RemoteConfigResolver' 2>/dev/nullRepository: spicetify/cli
Length of output: 41
🏁 Script executed:
#!/bin/bash
# Look for any integration tests or fixtures
find . -type f \( -name '*.js' -o -name '*.json' \) | xargs grep -l 'RemoteConfigResolver' 2>/dev/null | head -10Repository: spicetify/cli
Length of output: 113
🏁 Script executed:
#!/bin/bash
# Check git history to see if this was recently changed/fixed
git log --oneline -20 -- src/apply/apply.go 2>/dev/null | head -20Repository: spicetify/cli
Length of output: 132
🏁 Script executed:
#!/bin/bash
# Search for issues or comments about unbalanced braces in the repo
rg -i 'unbalanced|brace' --type=go src/apply/ 2>/dev/nullRepository: spicetify/cli
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Show the actual changes in the commit that fixed unbalanced braces
git show 152d12f -- src/apply/apply.go 2>/dev/null | head -100Repository: spicetify/cli
Length of output: 3079
🏁 Script executed:
#!/bin/bash
# Show the full diff for that commit
git diff 152d12f~1 152d12f -- src/apply/apply.go 2>/dev/null | grep -A 5 -B 5 'RemoteConfigResolver'Repository: spicetify/cli
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Check what the code looks like in the helper files that reference RemoteConfigResolver
cat jsHelper/expFeatures.js 2>/dev/null | grep -A 10 -B 10 'RemoteConfigResolver'Repository: spicetify/cli
Length of output: 2196
🏁 Script executed:
#!/bin/bash
# Check the other helper file
cat jsHelper/spicetifyWrapper.js 2>/dev/null | grep -A 10 -B 10 'RemoteConfigResolver'Repository: spicetify/cli
Length of output: 481
🏁 Script executed:
#!/bin/bash
# Verify the exact format string and count braces carefully
sed -n '485p' src/apply/apply.go | catRepository: spicetify/cli
Length of output: 271
🏁 Script executed:
#!/bin/bash
# Check if there's a test that shows expected output
find . -type f -name '*.go' -exec grep -l 'RemoteConfigResolver.*try\|catch.*RemoteConfigResolver' {} \;Repository: spicetify/cli
Length of output: 77
🏁 Script executed:
#!/bin/bash
# Look for any related issues or TODOs
rg -i 'todo|fixme|bug|brace' src/apply/apply.goRepository: spicetify/cli
Length of output: 39
🏁 Script executed:
#!/bin/bash
# Let me manually trace through the exact substitution to be absolutely certain
cat > /tmp/trace.py << 'EOF'
# Simulate the regex and format string substitution
# Example values that would match the regex
group1 = "Y.fromJSON(z);"
group2 = "Y.fromJSON"
group3 = "return someProvider,"
group4 = "{value:{localConfiguration"
# The format string from the code
fmt = "%stry{Spicetify.createInternalMap=%s}catch(_e){};%stry{Spicetify.RemoteConfigResolver=%s}}catch(_e){};{value:{localConfiguration"
# Perform substitution
result = fmt % (group1, group2, group3, group4)
print("Full formatted result:")
print(result)
print("\n" + "="*80 + "\n")
# Focus on the RemoteConfigResolver part
remote_part = f"try{{Spicetify.RemoteConfigResolver={group4}}}catch(_e){{}}"
print("RemoteConfigResolver section:")
print(remote_part)
print("\nBrace analysis:")
opens = 0
closes = 0
for i, char in enumerate(remote_part):
if char == '{':
opens += 1
print(f"Position {i}: '{char}' - Opens {opens} (depth: {opens})")
elif char == '}':
closes += 1
print(f"Position {i}: '{char}' - Closes {closes} (remaining open: {opens - closes})")
print(f"\nTotal: {opens} opening braces, {closes} closing braces")
print(f"Balanced: {opens == closes}")
EOF
python /tmp/trace.pyRepository: spicetify/cli
Length of output: 780
Fix unbalanced braces in the RemoteConfigResolver try-catch wrapper — produces invalid JavaScript syntax.
The format string on line 485 creates a try-catch block around Spicetify.RemoteConfigResolver assignment with an unclosed try{ brace. The current code produces only 2 closing braces (}}) before catch, but 3 are required to properly close the nested object literals and the try block:
// Current (invalid) — try block never closes:
try{Spicetify.RemoteConfigResolver={value:{localConfiguration}}catch(_e){};
// Correct (valid) — 3 closing braces:
try{Spicetify.RemoteConfigResolver={value:{localConfiguration}}}catch(_e){};Change }}catch to }}}catch on line 485:
- return fmt.Sprintf("%stry{Spicetify.createInternalMap=%s}catch(_e){};%stry{Spicetify.RemoteConfigResolver=%s}}catch(_e){};{value:{localConfiguration", submatches[1], submatches[2], submatches[3], submatches[4])
+ return fmt.Sprintf("%stry{Spicetify.createInternalMap=%s}catch(_e){};%stry{Spicetify.RemoteConfigResolver=%s}}}catch(_e){};{value:{localConfiguration", submatches[1], submatches[2], submatches[3], submatches[4])🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/apply/apply.go` at line 485, The formatted JS string building the
RemoteConfigResolver try-catch is missing a closing brace: in the fmt.Sprintf
that constructs the snippet assigning Spicetify.RemoteConfigResolver (the line
using submatches[1..4]), change the sequence right before catch from "}}catch"
to "}}}catch" so the nested object literal and the try block are properly closed
(i.e., ensure the format string around Spicetify.RemoteConfigResolver ends with
three closing braces before "catch(_e){};").
…teral cannot be wrapped
The regex only captures the START of an object literal ({value:{localConfiguration).
The rest continues in the original Spotify code. Wrapping this in try-catch
with any number of closing braces produces either invalid JS (}}) or truncated
semantics (}}}). Same issue as preprocess.go PlatformAPI capture.
Keep createInternalMap try-catch since it wraps a simple function reference.
|
I appreciate the want of the fix and the explanation of the issue, however:
I'm not really happy about it and am not even considering it to be merged |
|
Thanks for the review @rxri. I understand the concern about extensions, so let me clarify how the lazy getters actually work: Extensions are NOT affected. When an extension accesses Spicetify.Platform.PlayerAPI, the lazy getter fires immediately, calls the native getter, caches the result, and returns it — all in the same access. From the extension's perspective, the property is there and works normally. There's no waiting or polling needed. The only difference from the current behavior is when the native call happens: Before: All ~20 native getters called eagerly at startup → one crashes → whole app segfaults Screencast_20260217_235859.webmHowever, if you dont like the code you can reject it 😭 ❤️ |
|
What's the point of this if only one getter will always fail? Let's just find the one that doesn't work and not call it at all lol. This is literally over-engineered and I can tell it's AI because they like to do this even for simple issues |
|
Thanks for the suggestion but the real problem is on the spotify sides; what i meant, the crash happening on the spotify native c++ codes, so the js cannot catch the errors unfortuanly. What is that meaning is need extremely debug, so thats the basic solution. And yeah im using AI XD but yeah, in general your right, if you want to me contunie i will contunie to debug |
|
I am aware this is spotify's fault. They broke it. I said since the beginning that this is not our fault and this just proves it further.
It's over engineered for no reason. The AI should not be used for such an issue anyway. The |
|
yes, but if the home config and exp features is disabled then no marketplace and the spicetify without marketplace is nothing(this time include extensions) so the as i said, binary research is needed, and i skip that one, dont want to spend time on it, and use the working one since i dont need every api on spotify, so you can close the pr ❤️ |
Summary
Fixes #3695 — Spotify 1.2.82 on Linux segfaults on launch after
spicetify backup apply.Root Cause
Spicetify eagerly calls all
_platform.get*()native getter functions at startup inwaitForPlatform(). On Spotify 1.2.82 for Linux, one or more of these native getters triggers a SIGSEGV (segmentation fault) in Chromium's native layer. Since this is a native crash, JavaScripttry-catchcannot intercept it.Fix
Convert all PlatformAPI getter resolution from eager (called at startup) to lazy (
Object.definePropertygetters that resolve on first access):undefinedinstead of crashingChanges
jsHelper/spicetifyWrapper.js
waitForPlatform(): Replace eager_platform[key]()calls with lazyObject.definePropertygettersaddMissingPlatformAPIs(): Replace eagerRegistry.resolve()calls with lazy gettersjsHelper/homeConfig.js
Spicetify.Platform.Historybefore accessing.locationjsHelper/expFeatures.js
RemoteConfigDebugAPI?.getProperties()src/apply/apply.go
typeofcheck + try-catchRemoteConfigResolverandcreateInternalMapcaptures with try-catchSpicetifyHomeConfig.arrangewithtypeofcheck + fallbackTesting
Summary by CodeRabbit
Tests
Bug Fixes
New Features