Integrating Gatsby Image with the Airtable Source Plugin

I’m attempting to utilize gatsby-source-airtable to retrieve images from my Airtable database and then display them using the Gatsby Image component. However, I’m facing some challenges.

In my gatsby-config.js, I’ve set up the attachment column to act as a file node in this manner:

mapping: {'image': 'fileNode'}

When I run this GraphQL query in the GraphiQL tool, it works without any issues:

{
  airtable(table: {
    eq: "table-1"
  }, data: {
    slug: {
      eq: "test-1"
    }
  }) {
    data {
      image {
        localFiles {
          childImageSharp {
            fluid(maxWidth: 400) {
              src
            }
          }
        }
      }
    }
  }
}

This provides the correct image path, and I can access the image directly through the URL. However, when I try to implement this data with the Gatsby Image component in my React component, I receive the following error:

<Img fluid={post.data.image.localFiles.childImageSharp.fluid} />

export const query = graphql`
  query PostQuery {
    airtable(table: {
      eq: "table-1"
    }, data: {
      slug: {
        eq: "test-1"
      }
    }) {
      data {
        image {
          localFiles {
            childImageSharp {
              fluid(maxWidth: 400) { ...GatsbyImageSharpFluid }
            }
          }
        }
      }
    }
  }
`

The error I see states: “TypeError: Cannot read property ‘fluid’ of undefined”. What might be the issue here? I would really appreciate any guidance!

totally feel ya! that localFiles array tripped me up too. just switch to post.data.image.localFiles[0].childImageSharp.fluid, but remember to check if the array isn’t empty first to avoid any issues. airtable can return empty stuff, and you don’t wanna crash later.

The error happens because you’re treating an array like a single object. Airtable sends attachment fields as arrays through gatsby-source-airtable, even when there’s just one image. Your GraphQL query needs array indexing to prevent runtime crashes. Try localFiles[0] in your query, or add a null check before rendering. I’d console.log the whole post.data.image structure first - you’ll see exactly what you’re dealing with. Airtable sometimes returns empty arrays or null values when attachment fields are empty, so always code defensively.

You’re hitting this issue because localFiles is an array, but you’re trying to access .childImageSharp.fluid directly on it. You need to grab the first element instead. I ran into the same thing with Airtable attachments. Here’s the fix: In your component, change it to <Img fluid={post.data.image.localFiles[0].childImageSharp.fluid} />. Just make sure to add error checking first - test if the array isn’t empty before accessing it, or you’ll get undefined errors when images haven’t loaded or don’t exist.

Two things are happening here. First, like others said, localFiles is an array so you need to grab the first element. But there’s another gotcha - your GraphQL query in GraphiQL includes the src field but your component query uses the fragment ...GatsbyImageSharpFluid.

I’ve seen this exact thing break when there’s a mismatch between what you’re testing and what you’re actually querying. Make your component query match your working GraphiQL query:

fluid(maxWidth: 400) {
  src
  aspectRatio
  sizes
  srcSet
}

Or if you want to stick with the fragment, test it in GraphiQL first.

Also, add some safety checks since Airtable can return empty attachment fields:

{post.data.image?.localFiles?.[0]?.childImageSharp?.fluid && (
  <Img fluid={post.data.image.localFiles[0].childImageSharp.fluid} />
)}

I usually wrap a helper function around this because the path gets messy fast with multiple images per record.