Can't parse JSON

Hello!

I’m working on an FNF game and I’ve already asked this question before but nobody really helped me so here I am wondering if there are others who can help me. I was trying to add a new song to my fnf game when I ran into the following errors:

“Can’t parse JSON Script ‘Workspace.FNFStage.FNFHandle’ , line 305”

“Can’t Parse JSON Script ‘Players.HystericalBinky.PlayerGui.FNFEngine.Server’ , Line 52”

“Can’t Parse JSON Script ‘Players.TryingToMakeAnAcc.PlayerGui.FNFEngine.Server’ , Line 52”

I have no idea how JSON works as I followed a tutorial but they didn’t really explain how to add more songs. Here’s the JSON code for the song: JSON Error - Pastebin.com

And here is the code where it gives the error:

local basesong = game.HttpService:JSONDecode(song)
game.HttpService:JSONDecode(stage.Config.Song.Value.Value)
game.HttpService:JSONDecode(stage.Config.Song.Value.Value)

Can anyone help me out with this? I really can’t find anyone having this problem on YT or on the devforum and I’ve asked my friends to but they don’t know either. If u can’t then thank’s for at least tryna figure it out. If u think u can help me solve this then please reply! Thanks!

-HystericalBinky

3 Likes

You need to pass a table as the argument, not a value.

1 Like

so what would I change? again don’t know a single bit about JSON or how u script it to work in LUA scripts.

1 Like

Well, you could do it like this:

local Table = { Song = song, Stage = stage }

HttpService:JSONEncode(Table)
HttpService:JSONDecode(Table)

But, why do you need to in this case?

1 Like

well… the JSON code is in a value but I guess i’ll try it.

1 Like

Just remember it has to be a lua table.
It’ll only accept that.

1 Like

Well then why does it work on the other songs? they are values to but they work perfectly fine.

1 Like

I don’t know what “song” is, you should elaborate more so we can look into it.

1 Like

Well, basically once it decodes the JSON code it will play the song that u selected. which works in all my songs except this one for some reason.

Actually, JSONEncode requires a lua table, JSONEncode doesn’t necessarily have to be one, as it can also be a string.

Provide the full code so I can look into it, if you want.

Alright, here u go:

Script where error 1 occurs(line 305):

--\\ FNF Handler Server

--\\ Variables

local events = script.Parent.Events
local config = script.Parent.Config
local promptAEnter = script.Parent.MicrophoneA.Stem.Enter
local promptALeave = script.Parent.MicrophoneA.Stem.Leave
local promptBEnter = script.Parent.MicrophoneB.Stem.Enter
local promptBLeave = script.Parent.MicrophoneB.Stem.Leave
local songs = script.Parent.Songs
local settings = require(script.Parent.ReadMe)

local player1, player2 = nil, nil
local engine1, engine2 = nil, nil
local playing, songselecting = false, false

local microphone = script.Parent.Microphone
microphone.Parent = nil
microphone.Name = "\aFNFMicrophoneTool\a"

local amicro1 = script.Parent.MicrophoneA.Microphone
local amicro2 = script.Parent.MicrophoneB.Microphone

local tlboard = script.Parent.TLBoard
local tltext = tlboard.TLText
tlboard.Parent = nil

config.SelectTimeLeft.Changed:Connect(function()
	local t = "" .. math.ceil(config.SelectTimeLeft.Value)
	tlboard.G.Label.Text = t
	tlboard.G.Label.Overlay.Text = t
end)

local gamesignal = Instance.new("BindableEvent")

if not settings.ModsEnabled then
	for _, song in pairs(songs:GetChildren()) do
		if song:FindFirstChild("Modded") then
			song:Destroy()
		end
	end
end

local wait = function(n)
	n = n or 0
	assert(typeof(n)=="number", "Argument 1 must be a number")
	local s = tick()
	repeat game["Run Service"].Stepped:Wait() until tick()-s >= n
	return tick()-s
end

promptAEnter.Triggered:Connect(function(plr)
	if player1 then return end
	if plr == player2 then return end
	if not plr.Character then return end
	if playing then return end
	
	plr.Character.HumanoidRootPart.Anchored = true
	plr.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointA.CFrame
	player1 = plr
end)

promptBEnter.Triggered:Connect(function(plr)
	if player2 then return end
	if plr == player1 then return end
	if not plr.Character then return end
	if playing then return end
	
	plr.Character.HumanoidRootPart.Anchored = true
	plr.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointB.CFrame
	player2 = plr
end)

promptALeave.Triggered:Connect(function(plr)
	if plr ~= player1 then return end
	if not plr.Character then return end
	if playing then return end

	plr.Character.HumanoidRootPart.Anchored = false
	player1 = nil
end)

promptBLeave.Triggered:Connect(function(plr)
	if plr ~= player2 then return end
	if not plr.Character then return end
	if playing then return end

	plr.Character.HumanoidRootPart.Anchored = false
	player2 = nil
end)

--\\ Player Debugging

spawn(function()
	while wait() do
		if not playing then
			if player1 and player2 then
				gamesignal:Fire()
			else
				if typeof(player1) == "Instance" then
					if player1.Parent == nil then
						player1 = nil
					elseif player1.Character then
						local hum = player1.Character:FindFirstChildOfClass("Humanoid")
						if hum.Health == 0 then
							player1 = nil
						end
					else player1 = nil end
				end
				if typeof(player2) == "Instance" then
					if player2.Parent == nil then
						player2 = nil
					elseif player2.Character then
						local hum = player2.Character:FindFirstChildOfClass("Humanoid")
						if hum.Health == 0 then
							player2 = nil
						end
					else player2 = nil end
				end
				if player1 then
					promptALeave.Enabled = true
					promptAEnter.Enabled = false
				else
					promptALeave.Enabled = false
					promptAEnter.Enabled = true
				end
				if player2 then
					promptBLeave.Enabled = true
					promptBEnter.Enabled = false
				else
					promptBLeave.Enabled = false
					promptBEnter.Enabled = true
				end
			end
		end
	end
end)

--\\ Game

--\\ Points Update

config.P1Points.Changed:Connect(function()
	script.Parent.P1Board.G.PointsA.Text = config.P1Points.Value
	script.Parent.P1Board.G.PointsA.Overlay.Text = config.P1Points.Value
end)

config.P2Points.Changed:Connect(function()
	script.Parent.P2Board.G.PointsA.Text = config.P2Points.Value
	script.Parent.P2Board.G.PointsA.Overlay.Text = config.P2Points.Value
end)

--\\ Signal

gamesignal.Event:Connect(function()
	if playing then return end
	if not (player1 and player2) then return error("Player1 or Player2 don't exist!")end
	
	--\\ Set Default Values
	
	config.CleaningUp.Value = false
	playing = true
	config.TimePast.Value = -10
	
	--\\ Give Players UI

	engine1 = script.Parent.FNFEngine:Clone()
	engine2 = script.Parent.FNFEngine:Clone()

	engine1.Parent = player1.PlayerGui
	engine2.Parent = player2.PlayerGui

	engine1.Stage.Value = script.Parent
	engine2.Stage.Value = script.Parent

	engine1.PlayerSide.Value = "L"
	engine2.PlayerSide.Value = "R"

	engine1.Client.Disabled = false
	engine1.Server.Disabled = false

	engine2.Client.Disabled = false
	engine2.Server.Disabled = false
	
	config.P1Points.Value = 0
	config.P2Points.Value = 0
	
	player1.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointA.CFrame
	player2.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointB.CFrame
	
	--\\ Give Microphones
	
	local micro1, micro2 = microphone:Clone(), microphone:Clone()
	
	if settings.MicrophoneEnabled then
		micro1.Parent = workspace
		micro2.Parent = workspace
		amicro1.Parent = nil
		amicro2.Parent = nil
		player1.Character.Humanoid:EquipTool(micro1)
		player2.Character.Humanoid:EquipTool(micro2)
	end

	--\\ Disable Proximity Prompts

	promptAEnter.Enabled = false
	promptALeave.Enabled = false
	promptBEnter.Enabled = false
	promptBLeave.Enabled = false

	songselecting = true

	local startick = tick()
	local songvote1, songvote2 = nil,nil
	
	config.SelectTimeLeft.Value = 15
	
	tlboard.Parent = script.Parent
	
	local con = events.PlayerSongVote.OnServerEvent:Connect(function(invoker, song, mode)
		if not (typeof(song) == "string" or typeof(mode) == "string") then return end
		if invoker == player1 and not songvote1 then
			songvote1 = {song, mode}
		end
		if invoker == player2 and not songvote2 then
			songvote2 = {song, mode}
		end
	end)

	local songs = script.Parent.Songs
	local music = script.Parent.MusicPart

	repeat 
		wait()
		config.SelectTimeLeft.Value = 15-math.clamp(math.ceil(tick()-startick),0,15)
	until tick()-startick > 15 or (songvote1 and songvote2)

	con:Disconnect()
	
	tlboard.Parent = nil
	
	engine1.SongSelect:Destroy()
	engine2.SongSelect:Destroy()

	--\\ Song Assigning

	if songvote1 then
		local song = songvote1[1]
		local mode = songvote1[2]
		local songholder = songs:FindFirstChild(song)
		if songholder then
			if mode == "Hard" then
				songvote1 = songholder
			elseif mode == "Normal" then
				if songholder:FindFirstChild("Normal") then
					songvote1 = songholder.Normal:FindFirstChildOfClass("StringValue")
				else
					songvote1 = songholder
				end
			end
		end
	end
	
	if songvote2 then
		local song = songvote2[1]
		local mode = songvote2[2]
		local songholder = songs:FindFirstChild(song)
		if songholder then
			if mode == "Hard" then
				songvote2 = songholder
			elseif mode == "Normal" then
				if songholder:FindFirstChild("Normal") then
					songvote2 = songholder.Normal:FindFirstChildOfClass("StringValue")
				else
					songvote2 = songholder
				end
			end
		end
	end
	
	if not songvote1 then
		songvote1 = songvote2
	end
	
	if not songvote2 then
		songvote2 = songvote1
	end
	
	if not songvote1 and not songvote2 then
		config.Song.Value = songs:GetChildren()[math.random(1,#songs:GetChildren())]
	else
		local random = math.random(1,2)
		if random == 1 then config.Song.Value = songvote1 or songvote2 end
		if random == 2 then config.Song.Value = songvote2 or songvote1 end
	end


	local songholder = config.Song.Value:FindFirstAncestorOfClass("StringValue") or config.Song.Value

	script.Parent.MusicPart.Music:Stop()
	script.Parent.MusicPart.Vocals:Stop()

	local song = config.Song.Value.Value
	local basesong = game.HttpService:JSONDecode(song)
	song = basesong.song

	script.Parent.MusicPart.Music.SoundId = ""
	script.Parent.MusicPart.Vocals.SoundId = ""
		
	if songholder:FindFirstChild("Instrumental") then
		script.Parent.MusicPart.Music.SoundId = songholder.Instrumental.Value
		script.Parent.MusicPart.Music.PlaybackSpeed = songholder.Instrumental.PlaybackSpeed.Value
		script.Parent.MusicPart.Music.Volume = songholder.Instrumental.Volume.Value
		repeat wait() until script.Parent.MusicPart.Music.TimeLength > 0
	end
	if songholder:FindFirstChild("Sound") then
		script.Parent.MusicPart.Vocals.SoundId = songholder.Sound.Value
		script.Parent.MusicPart.Vocals.PlaybackSpeed = songholder.Sound.PlaybackSpeed.Value
		script.Parent.MusicPart.Vocals.Volume = songholder.Sound.Volume.Value
		repeat wait() until script.Parent.MusicPart.Vocals.TimeLength > 0
	end
	
	local activeSound = script.Parent.MusicPart.Music.SoundId ~= "" and script.Parent.MusicPart.Music or script.Parent.MusicPart.Vocals
	
	config.TimePast.Value = -4 / song.speed

	local lengthtween = game.TweenService:Create(config.TimePast,TweenInfo.new((activeSound.TimeLength+(4/song.speed)), Enum.EasingStyle.Linear,Enum.EasingDirection.In,0,false,0),
		{Value=activeSound.TimeLength})
	lengthtween:Play()
	
	script.Parent.MusicPart["3"]:Play()
	
	local waittime = 1 / song.speed
	
	wait(waittime)

	script.Parent.MusicPart["2"]:Play()

	wait(waittime)

	script.Parent.MusicPart["1"]:Play()

	wait(waittime)

	script.Parent.MusicPart["Go"]:Play()

	wait(waittime)
	
	script.Parent.MusicPart.Music:Play()
	script.Parent.MusicPart.Vocals:Play()
	script.Parent.MusicPart.Music.TimePosition = 0
	script.Parent.MusicPart.Vocals.TimePosition = 0
	
	--\\ Points System
	
	local psystem = events.AddPoints.Event:Connect(function(side, amt)
		if side == "L" then
			config.P1Points.Value += amt
		end
		if side == "R" then
			config.P2Points.Value += amt
		end
	end)
	
	--\\ Debugging

	local terminategame = false

	spawn(function()
		while not terminategame and wait() do
			if not player1 or not player2 then terminategame = true break end
		end
	end)
	
	lengthtween.Completed:Connect(function() 
		terminategame = true
		lengthtween:Destroy()	
	end)
	
	repeat wait() until terminategame

	terminategame = true
	config.CleaningUp.Value = true
	
	script.Parent.MusicPart.Music:Stop()
	script.Parent.MusicPart.Vocals:Stop()
	
	if player1.Parent ~= nil then engine1.Events.Stop:FireAllClients() end
	if player2.Parent ~= nil then engine2.Events.Stop:FireAllClients() end
	
	local winner = ""
	
	if config.P1Points.Value > config.P2Points.Value then
		winner = "P1"
	elseif config.P2Points.Value > config.P1Points.Value then
		winner = "P2"
	else
		winner = "P1P2"
	end
	
	--\\ Dispense Fireworks
	
	wait(2)
	if settings.FireworkEndEnabled then
		for _, obj in pairs(script.Parent.Fireworks:GetChildren()) do
			if winner:match(obj.Name) then
				obj.Fireworks:Play()
				for _, p in pairs(obj:GetChildren()) do
					if p:IsA("ParticleEmitter") then
						p:Emit(5)
					end
				end
			end
		end
	end
	
	wait(3)

	engine1:Destroy()
	engine2:Destroy()
	
	micro1:Destroy()
	micro2:Destroy()
	amicro1.Parent = script.Parent.MicrophoneA
	amicro2.Parent = script.Parent.MicrophoneB

	if player1.Parent ~= nil then player1.Character.HumanoidRootPart.Anchored = false end
	if player2.Parent ~= nil then player2.Character.HumanoidRootPart.Anchored = false end

	promptAEnter.Enabled = true
	promptALeave.Enabled = false
	promptBEnter.Enabled = true
	promptBLeave.Enabled = false
	
	config.P1Points.Value = 0
	config.P2Points.Value = 0

	player1, player2 = nil,nil
	playing = false
	
	config.Song.Value = nil
	config.TimePast.Value = -50
end)

“Server” script where error 2 and 3 occur(line 52):

--\\ FNF Server

--\\ Variables

local wait = function(n)
	n = n or 0
	assert(typeof(n)=="number", "Argument 1 must be a number")
	local s = tick()
	repeat game["Run Service"].Stepped:Wait() until tick()-s >= n
	return tick()-s
end

local player = script:FindFirstAncestorOfClass("Player")
local ui = script.Parent
local events = ui.Events
local config = ui.Config
local input = events.UserInput
local stage = ui.Stage.Value
local side = ui.Game:FindFirstChild(ui.PlayerSide.Value)
config.ObjectCount.Value = #ui:GetDescendants()

ui.Game.Visible = false

config.ServerSetup.Value = true

local function updatepoints()
	local lower = ui.LowerContainer
	local p1, p2 = stage.Config.P1Points.Value, stage.Config.P2Points.Value
	local total = p1+p2

	lower.PointsA.Text = ""..p1
	lower.PointsB.Text = ""..p2

	lower.PointsA.Overlay.Text = ""..p1
	lower.PointsB.Overlay.Text = ""..p2

	if p1 == 0 and p2 == 0 then
		lower.Bar.Background.Fill.Size = UDim2.new(0.5,0,1,0)
	else
		lower.Bar.Background.Fill.Size = UDim2.new(p1/total,0,1,0)
	end
end

updatepoints()

repeat wait() until stage.Config.Song.Value

ui.Game.Visible = true

--\\ Game

local basesong = game.HttpService:JSONDecode(stage.Config.Song.Value.Value)
local song = basesong.song

song.speed = song.speed or 1
song.bpm = song.bpm or 120

local function tomilseconds(seconds)
	return seconds*1000
end

local function toseconds(milliseconds)
	return milliseconds/1000
end

local function iseven(num)
	if math.floor(num) % 2 == 0 then return true else return false end
end

local function notetypeconvert(type)
	if tonumber(type) then
		if type == 0 then return "Left" end
		if type == 1 then return "Down" end
		if type == 2 then return "Up" end
		if type == 3 then return "Right" end
		if type > 3 then 
			return notetypeconvert(type-4), true
		end
	end
end

local templates = ui.Game.Templates

--\\ Ready Set Go

spawn(function()
	stage.MusicPart["2"].Played:Wait()
	ui.Ready.Visible = true

	stage.MusicPart["1"].Played:Wait()
	ui.Ready.Visible = false
	ui.Set.Visible = true

	stage.MusicPart["Go"].Played:Wait()
	ui.Set.Visible = false
	ui.Go.Visible = true

	spawn(function()
		wait(1 / song.speed)
		ui.Go.Visible = false
	end)
end)

--\\ Notes

repeat game["Run Service"].Stepped:Wait() until stage.Config.TimePast.Value > -4 / song.speed

local currentarrows = {}

local time = 1.75

spawn(function()
	local notes = basesong.notes or song.notes
	
	local printDebounce = false
	while wait() do
		updatepoints()

		--\\ Debugging

		if stage.Config.CleaningUp.Value then return end
		
		--\\ Notes
		for sectionnum, section in pairs(notes) do
			for notenum, note in pairs(section.sectionNotes) do
				local timeposition 	= note[1]
				local notetype 		= note[2]
				local notelength	= note[3]
				local timeframe = tomilseconds(time / song.speed)
				local timepast = tomilseconds(stage.Config.TimePast.Value)
				
				if timepast > timeposition - timeframe and timeposition and notetype and notelength then
					local side = section.mustHitSection
					local actualnotetype, oppositeSide = notetypeconvert(notetype)

					if oppositeSide then side = not side end
					side = side and "R" or "L"

					if not oppositeSide then ui.Side.Value = side end

					--\\ Delete note from table
					table.remove(section.sectionNotes, notenum)

					--\\ Add note to game
					local slot = templates[actualnotetype]:Clone()
					--slot.Frame.Bar.Size = UDim2.new(0.325,0,notelength/1000/song.speed,0)
					slot.Position = UDim2.new(1,0,6.666,0)
					slot.Parent = ui.Game[side].Arrows.IncomingArrows

					local tweeninfo = {time * (2 / song.speed),Enum.EasingStyle.Linear,Enum.EasingDirection.In,0,false,0}
					local properties = {Position=UDim2.new(1,0,-6.666,0)}

					events.TweenArrow:FireClient(player, slot, tweeninfo, properties)
					currentarrows[slot] = tick()

					spawn(function()
						wait(time * (2 / song.speed))
						slot:Destroy()
					end)
				else
					if not printDebounce then
						printDebounce = true
						spawn(function()
							wait(1)
							printDebounce = false
						end)
					end	
				end
			end
		end
	end
end)

--\\ Input

local function addpoints(n, direction)
	stage.Events.AddPoints:Fire(ui.PlayerSide.Value, n, direction)
end

input.OnServerEvent:Connect(function(invoker, direction, type, obj, position)
	if typeof(direction) ~= "string" then return end
	if typeof(type) ~= "EnumItem" then return end
	if obj == "missed" then addpoints(-50) return end
	if typeof(obj) ~= "Instance" then return end
	if typeof(position) ~= "UDim2" then return end

	if stage.Config.CleaningUp.Value then return end

	if invoker == player then
		local arrows = ui.Game[ui.PlayerSide.Value].Arrows.IncomingArrows
		for _, arrow in pairs(arrows:GetChildren()) do
			local dist = math.abs(position.Y.Scale)
			if arrow.Name == direction and arrow == obj and dist <= 1 and arrow.Frame.Arrow.Visible then
				arrow.Frame.Arrow.Visible = false

				--\\ Points

				if dist <= 0.075 then
					addpoints(500, direction) -- Sick!
				elseif dist <= 0.25 then
					addpoints(350, direction) -- Good!
				elseif dist <= 0.5 then
					addpoints(200, direction) -- Nice.
				elseif dist <= 1 then
					addpoints(50, direction) -- Bad.
				end

				--\\ Player Interaction

				if ui.PlayerSide.Value == "L" then
					stage.Events.Player1Hit:FireAllClients(direction, type)
				end
				if ui.PlayerSide.Value == "R" then
					stage.Events.Player2Hit:FireAllClients(direction, type)
				end
			end
		end
	end
end)

the JSON code is in the post.

also the error happens when decoding not encoding.

Can you comment the lines out? It’ll be easier to find them that way.

Like put numbers in front of em?

Just make the lines a comment (the error ones).

--\\ FNF Handler Server

--\\ Variables

local events = script.Parent.Events
local config = script.Parent.Config
local promptAEnter = script.Parent.MicrophoneA.Stem.Enter
local promptALeave = script.Parent.MicrophoneA.Stem.Leave
local promptBEnter = script.Parent.MicrophoneB.Stem.Enter
local promptBLeave = script.Parent.MicrophoneB.Stem.Leave
local songs = script.Parent.Songs
local settings = require(script.Parent.ReadMe)

local player1, player2 = nil, nil
local engine1, engine2 = nil, nil
local playing, songselecting = false, false

local microphone = script.Parent.Microphone
microphone.Parent = nil
microphone.Name = "\aFNFMicrophoneTool\a"

local amicro1 = script.Parent.MicrophoneA.Microphone
local amicro2 = script.Parent.MicrophoneB.Microphone

local tlboard = script.Parent.TLBoard
local tltext = tlboard.TLText
tlboard.Parent = nil

config.SelectTimeLeft.Changed:Connect(function()
	local t = "" .. math.ceil(config.SelectTimeLeft.Value)
	tlboard.G.Label.Text = t
	tlboard.G.Label.Overlay.Text = t
end)

local gamesignal = Instance.new("BindableEvent")

if not settings.ModsEnabled then
	for _, song in pairs(songs:GetChildren()) do
		if song:FindFirstChild("Modded") then
			song:Destroy()
		end
	end
end

local wait = function(n)
	n = n or 0
	assert(typeof(n)=="number", "Argument 1 must be a number")
	local s = tick()
	repeat game["Run Service"].Stepped:Wait() until tick()-s >= n
	return tick()-s
end

promptAEnter.Triggered:Connect(function(plr)
	if player1 then return end
	if plr == player2 then return end
	if not plr.Character then return end
	if playing then return end
	
	plr.Character.HumanoidRootPart.Anchored = true
	plr.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointA.CFrame
	player1 = plr
end)

promptBEnter.Triggered:Connect(function(plr)
	if player2 then return end
	if plr == player1 then return end
	if not plr.Character then return end
	if playing then return end
	
	plr.Character.HumanoidRootPart.Anchored = true
	plr.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointB.CFrame
	player2 = plr
end)

promptALeave.Triggered:Connect(function(plr)
	if plr ~= player1 then return end
	if not plr.Character then return end
	if playing then return end

	plr.Character.HumanoidRootPart.Anchored = false
	player1 = nil
end)

promptBLeave.Triggered:Connect(function(plr)
	if plr ~= player2 then return end
	if not plr.Character then return end
	if playing then return end

	plr.Character.HumanoidRootPart.Anchored = false
	player2 = nil
end)

--\\ Player Debugging

spawn(function()
	while wait() do
		if not playing then
			if player1 and player2 then
				gamesignal:Fire()
			else
				if typeof(player1) == "Instance" then
					if player1.Parent == nil then
						player1 = nil
					elseif player1.Character then
						local hum = player1.Character:FindFirstChildOfClass("Humanoid")
						if hum.Health == 0 then
							player1 = nil
						end
					else player1 = nil end
				end
				if typeof(player2) == "Instance" then
					if player2.Parent == nil then
						player2 = nil
					elseif player2.Character then
						local hum = player2.Character:FindFirstChildOfClass("Humanoid")
						if hum.Health == 0 then
							player2 = nil
						end
					else player2 = nil end
				end
				if player1 then
					promptALeave.Enabled = true
					promptAEnter.Enabled = false
				else
					promptALeave.Enabled = false
					promptAEnter.Enabled = true
				end
				if player2 then
					promptBLeave.Enabled = true
					promptBEnter.Enabled = false
				else
					promptBLeave.Enabled = false
					promptBEnter.Enabled = true
				end
			end
		end
	end
end)

--\\ Game

--\\ Points Update

config.P1Points.Changed:Connect(function()
	script.Parent.P1Board.G.PointsA.Text = config.P1Points.Value
	script.Parent.P1Board.G.PointsA.Overlay.Text = config.P1Points.Value
end)

config.P2Points.Changed:Connect(function()
	script.Parent.P2Board.G.PointsA.Text = config.P2Points.Value
	script.Parent.P2Board.G.PointsA.Overlay.Text = config.P2Points.Value
end)

--\\ Signal

gamesignal.Event:Connect(function()
	if playing then return end
	if not (player1 and player2) then return error("Player1 or Player2 don't exist!")end
	
	--\\ Set Default Values
	
	config.CleaningUp.Value = false
	playing = true
	config.TimePast.Value = -10
	
	--\\ Give Players UI

	engine1 = script.Parent.FNFEngine:Clone()
	engine2 = script.Parent.FNFEngine:Clone()

	engine1.Parent = player1.PlayerGui
	engine2.Parent = player2.PlayerGui

	engine1.Stage.Value = script.Parent
	engine2.Stage.Value = script.Parent

	engine1.PlayerSide.Value = "L"
	engine2.PlayerSide.Value = "R"

	engine1.Client.Disabled = false
	engine1.Server.Disabled = false

	engine2.Client.Disabled = false
	engine2.Server.Disabled = false
	
	config.P1Points.Value = 0
	config.P2Points.Value = 0
	
	player1.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointA.CFrame
	player2.Character.HumanoidRootPart.CFrame = script.Parent.PlayerPointB.CFrame
	
	--\\ Give Microphones
	
	local micro1, micro2 = microphone:Clone(), microphone:Clone()
	
	if settings.MicrophoneEnabled then
		micro1.Parent = workspace
		micro2.Parent = workspace
		amicro1.Parent = nil
		amicro2.Parent = nil
		player1.Character.Humanoid:EquipTool(micro1)
		player2.Character.Humanoid:EquipTool(micro2)
	end

	--\\ Disable Proximity Prompts

	promptAEnter.Enabled = false
	promptALeave.Enabled = false
	promptBEnter.Enabled = false
	promptBLeave.Enabled = false

	songselecting = true

	local startick = tick()
	local songvote1, songvote2 = nil,nil
	
	config.SelectTimeLeft.Value = 15
	
	tlboard.Parent = script.Parent
	
	local con = events.PlayerSongVote.OnServerEvent:Connect(function(invoker, song, mode)
		if not (typeof(song) == "string" or typeof(mode) == "string") then return end
		if invoker == player1 and not songvote1 then
			songvote1 = {song, mode}
		end
		if invoker == player2 and not songvote2 then
			songvote2 = {song, mode}
		end
	end)

	local songs = script.Parent.Songs
	local music = script.Parent.MusicPart

	repeat 
		wait()
		config.SelectTimeLeft.Value = 15-math.clamp(math.ceil(tick()-startick),0,15)
	until tick()-startick > 15 or (songvote1 and songvote2)

	con:Disconnect()
	
	tlboard.Parent = nil
	
	engine1.SongSelect:Destroy()
	engine2.SongSelect:Destroy()

	--\\ Song Assigning

	if songvote1 then
		local song = songvote1[1]
		local mode = songvote1[2]
		local songholder = songs:FindFirstChild(song)
		if songholder then
			if mode == "Hard" then
				songvote1 = songholder
			elseif mode == "Normal" then
				if songholder:FindFirstChild("Normal") then
					songvote1 = songholder.Normal:FindFirstChildOfClass("StringValue")
				else
					songvote1 = songholder
				end
			end
		end
	end
	
	if songvote2 then
		local song = songvote2[1]
		local mode = songvote2[2]
		local songholder = songs:FindFirstChild(song)
		if songholder then
			if mode == "Hard" then
				songvote2 = songholder
			elseif mode == "Normal" then
				if songholder:FindFirstChild("Normal") then
					songvote2 = songholder.Normal:FindFirstChildOfClass("StringValue")
				else
					songvote2 = songholder
				end
			end
		end
	end
	
	if not songvote1 then
		songvote1 = songvote2
	end
	
	if not songvote2 then
		songvote2 = songvote1
	end
	
	if not songvote1 and not songvote2 then
		config.Song.Value = songs:GetChildren()[math.random(1,#songs:GetChildren())]
	else
		local random = math.random(1,2)
		if random == 1 then config.Song.Value = songvote1 or songvote2 end
		if random == 2 then config.Song.Value = songvote2 or songvote1 end
	end


	local songholder = config.Song.Value:FindFirstAncestorOfClass("StringValue") or config.Song.Value

	script.Parent.MusicPart.Music:Stop()
	script.Parent.MusicPart.Vocals:Stop()

	local song = config.Song.Value.Value

        -- ERROR HERE!!!

	local basesong = game.HttpService:JSONDecode(song)
	song = basesong.song

	script.Parent.MusicPart.Music.SoundId = ""
	script.Parent.MusicPart.Vocals.SoundId = ""
		
	if songholder:FindFirstChild("Instrumental") then
		script.Parent.MusicPart.Music.SoundId = songholder.Instrumental.Value
		script.Parent.MusicPart.Music.PlaybackSpeed = songholder.Instrumental.PlaybackSpeed.Value
		script.Parent.MusicPart.Music.Volume = songholder.Instrumental.Volume.Value
		repeat wait() until script.Parent.MusicPart.Music.TimeLength > 0
	end
	if songholder:FindFirstChild("Sound") then
		script.Parent.MusicPart.Vocals.SoundId = songholder.Sound.Value
		script.Parent.MusicPart.Vocals.PlaybackSpeed = songholder.Sound.PlaybackSpeed.Value
		script.Parent.MusicPart.Vocals.Volume = songholder.Sound.Volume.Value
		repeat wait() until script.Parent.MusicPart.Vocals.TimeLength > 0
	end
	
	local activeSound = script.Parent.MusicPart.Music.SoundId ~= "" and script.Parent.MusicPart.Music or script.Parent.MusicPart.Vocals
	
	config.TimePast.Value = -4 / song.speed

	local lengthtween = game.TweenService:Create(config.TimePast,TweenInfo.new((activeSound.TimeLength+(4/song.speed)), Enum.EasingStyle.Linear,Enum.EasingDirection.In,0,false,0),
		{Value=activeSound.TimeLength})
	lengthtween:Play()
	
	script.Parent.MusicPart["3"]:Play()
	
	local waittime = 1 / song.speed
	
	wait(waittime)

	script.Parent.MusicPart["2"]:Play()

	wait(waittime)

	script.Parent.MusicPart["1"]:Play()

	wait(waittime)

	script.Parent.MusicPart["Go"]:Play()

	wait(waittime)
	
	script.Parent.MusicPart.Music:Play()
	script.Parent.MusicPart.Vocals:Play()
	script.Parent.MusicPart.Music.TimePosition = 0
	script.Parent.MusicPart.Vocals.TimePosition = 0
	
	--\\ Points System
	
	local psystem = events.AddPoints.Event:Connect(function(side, amt)
		if side == "L" then
			config.P1Points.Value += amt
		end
		if side == "R" then
			config.P2Points.Value += amt
		end
	end)
	
	--\\ Debugging

	local terminategame = false

	spawn(function()
		while not terminategame and wait() do
			if not player1 or not player2 then terminategame = true break end
		end
	end)
	
	lengthtween.Completed:Connect(function() 
		terminategame = true
		lengthtween:Destroy()	
	end)
	
	repeat wait() until terminategame

	terminategame = true
	config.CleaningUp.Value = true
	
	script.Parent.MusicPart.Music:Stop()
	script.Parent.MusicPart.Vocals:Stop()
	
	if player1.Parent ~= nil then engine1.Events.Stop:FireAllClients() end
	if player2.Parent ~= nil then engine2.Events.Stop:FireAllClients() end
	
	local winner = ""
	
	if config.P1Points.Value > config.P2Points.Value then
		winner = "P1"
	elseif config.P2Points.Value > config.P1Points.Value then
		winner = "P2"
	else
		winner = "P1P2"
	end
	
	--\\ Dispense Fireworks
	
	wait(2)
	if settings.FireworkEndEnabled then
		for _, obj in pairs(script.Parent.Fireworks:GetChildren()) do
			if winner:match(obj.Name) then
				obj.Fireworks:Play()
				for _, p in pairs(obj:GetChildren()) do
					if p:IsA("ParticleEmitter") then
						p:Emit(5)
					end
				end
			end
		end
	end
	
	wait(3)

	engine1:Destroy()
	engine2:Destroy()
	
	micro1:Destroy()
	micro2:Destroy()
	amicro1.Parent = script.Parent.MicrophoneA
	amicro2.Parent = script.Parent.MicrophoneB

	if player1.Parent ~= nil then player1.Character.HumanoidRootPart.Anchored = false end
	if player2.Parent ~= nil then player2.Character.HumanoidRootPart.Anchored = false end

	promptAEnter.Enabled = true
	promptALeave.Enabled = false
	promptBEnter.Enabled = true
	promptBLeave.Enabled = false
	
	config.P1Points.Value = 0
	config.P2Points.Value = 0

	player1, player2 = nil,nil
	playing = false
	
	config.Song.Value = nil
	config.TimePast.Value = -50
end)
--\\ FNF Server

--\\ Variables

local wait = function(n)
	n = n or 0
	assert(typeof(n)=="number", "Argument 1 must be a number")
	local s = tick()
	repeat game["Run Service"].Stepped:Wait() until tick()-s >= n
	return tick()-s
end

local player = script:FindFirstAncestorOfClass("Player")
local ui = script.Parent
local events = ui.Events
local config = ui.Config
local input = events.UserInput
local stage = ui.Stage.Value
local side = ui.Game:FindFirstChild(ui.PlayerSide.Value)
config.ObjectCount.Value = #ui:GetDescendants()

ui.Game.Visible = false

config.ServerSetup.Value = true

local function updatepoints()
	local lower = ui.LowerContainer
	local p1, p2 = stage.Config.P1Points.Value, stage.Config.P2Points.Value
	local total = p1+p2

	lower.PointsA.Text = ""..p1
	lower.PointsB.Text = ""..p2

	lower.PointsA.Overlay.Text = ""..p1
	lower.PointsB.Overlay.Text = ""..p2

	if p1 == 0 and p2 == 0 then
		lower.Bar.Background.Fill.Size = UDim2.new(0.5,0,1,0)
	else
		lower.Bar.Background.Fill.Size = UDim2.new(p1/total,0,1,0)
	end
end

updatepoints()

repeat wait() until stage.Config.Song.Value

ui.Game.Visible = true

--\\ Game

-- ERROR HERE!!!

local basesong = game.HttpService:JSONDecode(stage.Config.Song.Value.Value)
local song = basesong.song

song.speed = song.speed or 1
song.bpm = song.bpm or 120

local function tomilseconds(seconds)
	return seconds*1000
end

local function toseconds(milliseconds)
	return milliseconds/1000
end

local function iseven(num)
	if math.floor(num) % 2 == 0 then return true else return false end
end

local function notetypeconvert(type)
	if tonumber(type) then
		if type == 0 then return "Left" end
		if type == 1 then return "Down" end
		if type == 2 then return "Up" end
		if type == 3 then return "Right" end
		if type > 3 then 
			return notetypeconvert(type-4), true
		end
	end
end

local templates = ui.Game.Templates

--\\ Ready Set Go

spawn(function()
	stage.MusicPart["2"].Played:Wait()
	ui.Ready.Visible = true

	stage.MusicPart["1"].Played:Wait()
	ui.Ready.Visible = false
	ui.Set.Visible = true

	stage.MusicPart["Go"].Played:Wait()
	ui.Set.Visible = false
	ui.Go.Visible = true

	spawn(function()
		wait(1 / song.speed)
		ui.Go.Visible = false
	end)
end)

--\\ Notes

repeat game["Run Service"].Stepped:Wait() until stage.Config.TimePast.Value > -4 / song.speed

local currentarrows = {}

local time = 1.75

spawn(function()
	local notes = basesong.notes or song.notes
	
	local printDebounce = false
	while wait() do
		updatepoints()

		--\\ Debugging

		if stage.Config.CleaningUp.Value then return end
		
		--\\ Notes
		for sectionnum, section in pairs(notes) do
			for notenum, note in pairs(section.sectionNotes) do
				local timeposition 	= note[1]
				local notetype 		= note[2]
				local notelength	= note[3]
				local timeframe = tomilseconds(time / song.speed)
				local timepast = tomilseconds(stage.Config.TimePast.Value)
				
				if timepast > timeposition - timeframe and timeposition and notetype and notelength then
					local side = section.mustHitSection
					local actualnotetype, oppositeSide = notetypeconvert(notetype)

					if oppositeSide then side = not side end
					side = side and "R" or "L"

					if not oppositeSide then ui.Side.Value = side end

					--\\ Delete note from table
					table.remove(section.sectionNotes, notenum)

					--\\ Add note to game
					local slot = templates[actualnotetype]:Clone()
					--slot.Frame.Bar.Size = UDim2.new(0.325,0,notelength/1000/song.speed,0)
					slot.Position = UDim2.new(1,0,6.666,0)
					slot.Parent = ui.Game[side].Arrows.IncomingArrows

					local tweeninfo = {time * (2 / song.speed),Enum.EasingStyle.Linear,Enum.EasingDirection.In,0,false,0}
					local properties = {Position=UDim2.new(1,0,-6.666,0)}

					events.TweenArrow:FireClient(player, slot, tweeninfo, properties)
					currentarrows[slot] = tick()

					spawn(function()
						wait(time * (2 / song.speed))
						slot:Destroy()
					end)
				else
					if not printDebounce then
						printDebounce = true
						spawn(function()
							wait(1)
							printDebounce = false
						end)
					end	
				end
			end
		end
	end
end)

--\\ Input

local function addpoints(n, direction)
	stage.Events.AddPoints:Fire(ui.PlayerSide.Value, n, direction)
end

input.OnServerEvent:Connect(function(invoker, direction, type, obj, position)
	if typeof(direction) ~= "string" then return end
	if typeof(type) ~= "EnumItem" then return end
	if obj == "missed" then addpoints(-50) return end
	if typeof(obj) ~= "Instance" then return end
	if typeof(position) ~= "UDim2" then return end

	if stage.Config.CleaningUp.Value then return end

	if invoker == player then
		local arrows = ui.Game[ui.PlayerSide.Value].Arrows.IncomingArrows
		for _, arrow in pairs(arrows:GetChildren()) do
			local dist = math.abs(position.Y.Scale)
			if arrow.Name == direction and arrow == obj and dist <= 1 and arrow.Frame.Arrow.Visible then
				arrow.Frame.Arrow.Visible = false

				--\\ Points

				if dist <= 0.075 then
					addpoints(500, direction) -- Sick!
				elseif dist <= 0.25 then
					addpoints(350, direction) -- Good!
				elseif dist <= 0.5 then
					addpoints(200, direction) -- Nice.
				elseif dist <= 1 then
					addpoints(50, direction) -- Bad.
				end

				--\\ Player Interaction

				if ui.PlayerSide.Value == "L" then
					stage.Events.Player1Hit:FireAllClients(direction, type)
				end
				if ui.PlayerSide.Value == "R" then
					stage.Events.Player2Hit:FireAllClients(direction, type)
				end
			end
		end
	end
end)

Can I see the Value object?
It seems like you’re trying to access Value.song.

Also, you need to encode the table in order to decode it.

HP Enhanced Lighting (gyazo.com)

Based on that, it seems like you’re trying to access Value twice:

local song = config.Song.Value.Value

Edit - Noticed the name was also Value.
I’ll look into it.

The 2nd value is for checking the property “Value” of the value.

What happens when you decode it via a direct table instead of the value?
Because the value is a string, I’m pretty sure you’ll need a direct reference to a lua table, not via a object.