ScriptableRenderPass causes Exception: FindShaderByName can't be called during Serialization

I’ve been trying to add custom post processing effects to my project in URP, and have followed these tutorials:

Both of these implementations have caused the error “UnityException: FindShaderByName is not allowed to be called during serialization, call it from OnEnable instead. Called from ScriptableObject ‘QuantizationFeature’”.

Here is the QuantizationFeature.cs file:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

[System.Serializable]
public class QuantizationFeature : ScriptableRendererFeature
{
    QuantizationPass Pass;

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        renderer.EnqueuePass(Pass);
    }

    public override void Create()
    {
        Pass = new QuantizationPass();
    }
}

And the QuantizationPass.cs file:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;

[System.Serializable]
public class QuantizationPass : ScriptableRenderPass
{
    RenderTargetIdentifier Source;
    RenderTargetIdentifier Quantize;

    readonly int QuantizeID = Shader.PropertyToID("_Temp");

    private Material Mat;

    public QuantizationPass()
    {
        if (!Mat)
        {
            Mat = CoreUtils.CreateEngineMaterial("Custom/Quantization");
        }

        renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing;
    }

    public override void OnCameraSetup(CommandBuffer cmd, ref RenderingData renderingData)
    {
        RenderTextureDescriptor descriptor = renderingData.cameraData.cameraTargetDescriptor;
        Source = renderingData.cameraData.renderer.cameraColorTarget;
        cmd.GetTemporaryRT(QuantizeID, descriptor, FilterMode.Bilinear);
        Quantize = new RenderTargetIdentifier();
    }

    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        CommandBuffer commandBuffer = CommandBufferPool.Get("QuantizationFeature");
        VolumeStack volumes = VolumeManager.instance.stack;
        QuantizationVolumeComponent QuantizeData = volumes.GetComponent<QuantizationVolumeComponent>();

        if (QuantizeData.IsActive())
        {
            Mat.SetInt("_Layers", (int)QuantizeData.Layers);

            Blit(commandBuffer, Source, Quantize, Mat, 0);
            Blit(commandBuffer, Quantize, Source);
        }

        context.ExecuteCommandBuffer(commandBuffer);
        CommandBufferPool.Release(commandBuffer);
    }

    public override void OnCameraCleanup(CommandBuffer cmd)
    {
        cmd.ReleaseTemporaryRT(QuantizeID);
    }
}

As far as I can tell, the code follow the Youtube tutorial just fine, and he didn’t seem to run into the error at all. Additionally, (and probably related to the error), my QuantizationPass will not execute. I have set breakpoints in all functions in the class and none are hit except in the Constructor. The error seems to come from using CoreUtils.CreateEngineMaterial in the constructor, but I’m not sure why.

If it matters, I previously set up a URP Asset and Universal Renderer Data with some masking effects for my project, and I did ensure that that is the active Render Pipeline in ProjectSettings->Graphics, and that I added the QuantizationFeature to the Universal Render Data as a Renderer Feature. The other, built-in Post Processing effects work fine with URP, but trying to activate and use the Quantization one seems to do nothing.

This is my first time working with URP so I may be missing something obvious, but I couldn’t find any other resources online referencing the same issue.

Resolved by removing [System.Serializable] before both classes.