Block validator error: whitespace validation function not working

9 replies
Last updated: Oct 20, 2021
Hello, I am trying to use this (https://github.com/coreyward/sanity-pills/blob/master/src/lib/blockValidator.js ) validation function for no trailing/leading whitespaces, but I get this error in sanity (screenshot).

validation: (Rule) => Rule.required().custom((blocks) => {
   const offendingPaths = (blocks || [])
      .filter(({ _type, children }) => {
         if (_type !== "block") return false;

         const { 0: first, length, [length - 1]: last } = children || [];

         return first?.text.startsWith(" ") || last?.text.endsWith(" ")
      })
      .map((block, index) => [{ _key: block._key }] || [index]);
   return (
      offendingPaths.length === 0 || {
         message: "Blocks cannot start or end with whitespace",
         paths: offendingPaths,
      }
   )
}),
Can anyone point me in the right direction?
AI Update

Looking at your code, the issue is likely that you're trying to access properties on children that might be undefined or empty. The error is probably "Cannot read properties of undefined" when trying to access .text on first or last.

Here's the corrected validation function with proper null/undefined checks:

validation: (Rule) => Rule.required().custom((blocks) => {
   const offendingPaths = (blocks || [])
      .filter(({ _type, children }) => {
         if (_type !== "block" || !children || children.length === 0) return false;

         const { 0: first, length, [length - 1]: last } = children;

         // Check if first/last exist and have text property before checking whitespace
         return (first?.text && first.text.startsWith(" ")) || 
                (last?.text && last.text.endsWith(" "));
      })
      .map((block, index) => [{ _key: block._key }] || [index]);
   
   return (
      offendingPaths.length === 0 || {
         message: "Blocks cannot start or end with whitespace",
         paths: offendingPaths,
      }
   );
})

The key changes:

  1. Added children.length === 0 check: Ensures children array isn't empty before trying to access its elements
  2. Strengthened the conditional: Changed from first?.text.startsWith(" ") to first?.text && first.text.startsWith(" ") to ensure text property exists before calling string methods on it

The original sanity-pills blockValidator.js code works in many cases, but Portable Text blocks can have edge cases where children spans don't have a text property (like inline objects or custom marks), which causes the error you're seeing.

This validation approach is useful for maintaining clean content in your Portable Text fields, ensuring editors don't accidentally leave trailing or leading spaces that could cause formatting issues in your frontend.

Show original thread
9 replies
Under which field are you placing this rule? it looks like
blocks
might not be an array
adding a bit more code:
export default {
   name: "instructor",
   title: "Instructor",
   type: "document",
   fields: [
      {
         name: "name",
         title: "Name",
         type: "string",
         validation: << rule is here >>,
      },
      {
         name: "bio",
         title: "Bio",
         type: "text",
      },... ]}

Under which field are you placing this rule? it looks like
blocks
might not be an array
ah, the rule you’re using only applies to portable text fields, for a field of type string it’d be something like this:

validation: Rule => Rule.custom(name => {
  if (name.startsWith(' ') || name.endsWidth(' ')) {
    return 'No trailing space'
  }
  return true
})
something like that
check out the 2nd example in this section https://www.sanity.io/docs/validation#091e10f957aa
oh, okay, so I should also add
    if (typeof name === 'undefined') {
      return false
    }
meaning that it will not allow the value ‘undefined’, right?
yeah I think so!
ooh it makes sense, becausee if we got to the namee.startsWith part, it would crash, so we have to check for them before that
took me a bit, thank you

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?