I was having a bit of a struggle again getting my data to play along with graphql. Something like this is not a problem:
[{
"coverImage": {
"url": "http://example.com/assets/someimage.png"
}
}]
Neither is:
[{
"coverImage": {
"url": "/assets/someimage.png"
}
}]
But this:
[{
"coverImage": {
"url": "assets/someimage.png"
}
}]
or this:
[{
"coverImage": {
"url": "assets/someimage.png"
}
}]
or this:
[{
"coverImage": {
"filepath": "assets/someimage.png"
}
}]
results in a schema where you can't query the field from coverImage anymore. If I do I get this error:
UNHANDLED REJECTION Error: You supplied a GraphQL document with validation errors:
Field "filepath" of type "File" must have a selection of subfields. Did you mean "filepath { ... }"?
at Object.validate (/Users/me/project/node_modules/relay-compiler/lib/RelayValidator.js:19:17)
Does that make sense?
I believe that certain fields that look like files are actually turned into file nodes which is why you are getting the missing field error. I'm not sure what the use case was for that behavior tho
Yeah, that's the issue...
The use case is/was markdown frontmatter e.g.
---
title: "yo, cool post"
coverImage: "./my-sweet-cover-image.jpg"
---
A post about pure awesomeness.
The coverImage would automatically be converted to a link to its fileNode so you could write queries to automatically pull in that image w/ resizing, etc.
But yeah, right now the check isn't safe as it takes anything that looks like a relative link to a file.
Probably what we should do is recurse up the node's parents and make sure that it has a File ancestor.
@KyleAMathews ah well I was planning to do something similar. The assets are downloaded and placed relative to my data json, and I'd like those images to go through the sharp plugins. It's just that my images now have more fields besides url like title, size, width, height, but those are not crucial. So for now I could just replace the image data objects with strings holding the relative path to the file. If I do that things should get picked up by the sharp plugins?
yup! You'll be able to write queries like:
{
coverImage {
filePath {
childImageSharp {
responsiveSizes(maxWidth: 640) {
src
srcSet
}
}
}
}
Nice! That would have taken me a while to figure out ๐
I'm starting to understand the graphiql browser better now. I kept clicking on the function names / constructor, probably because their color stands out more. But then you only see the arguments and not the fields and methods (or whatever they're called) ๐
@KyleAMathews some of my data doesn't have a coverImage, and it should be optional. Is it possible to only make a query like that if the data is available? Or otherwise define a fallback?
The query returns null for coverImage which then leeds to this error:
message: 'Path must be a string. Received undefined',
locations: [ [Object] ],
path: [ 'allWorkJson', 'edges', 1, 'node', 'coverImage' ] },
{ TypeError: Path must be a string. Received undefined
at assertPath (path.js:7:11)
at Object.resolve (path.js:1146:7)
at resolve (/Users/me/project/node_modules/gatsby/dist/schema/infer-graphql-type.js:335:41)
So for the type WorkJson, none of the nodes have coverImage?
Can you make your question more specific? Queries are always optional since you have to write them :-)
@KyleAMathews For type WorkJson most of them have a coverImage set to a filepath, some don't have the property in the json source.
I'm querying all WorkJson for an overview page. So some of the data has coverImage set to a path and others return with coverImage set to null
When does the previous error happen then?
@KyleAMathews At bootstrap. So when the index page query is executed I guess?
I can get into the graphiql interface and execute the query there. I see the same error.
What line of code is that? There should never be an error querying null data. Unless ooo... is this when it tries to load the File node?
This is my graphiql query
{
allWorkJson {
edges {
node {
coverImage {
childImageSharp {
responsiveSizes (maxWidth: 200) {
src
}
}
}
}
}
}
}
And this the output
{
"data": {
"allWorkJson": {
"edges": [
{
"node": {
"coverImage": {
"childImageSharp": {
"responsiveSizes": {
"src": "/c51fc37d9860daff27cb3ebd113d360b-maxWidth=200&quality=50&pngCompressionLevel=9&width=200.png"
}
}
}
}
},
{
"node": {
"coverImage": null
}
},
{
"node": {
"coverImage": null
}
},
{
"node": {
"coverImage": {
"childImageSharp": {
"responsiveSizes": {
"src": "/53e9433574ffb78ca12150cf9c58b9a2-maxWidth=200&quality=50&pngCompressionLevel=9&width=200.png"
}
}
}
}
},
{
"node": {
"coverImage": null
}
},
{
"node": {
"coverImage": null
}
},
{
"node": {
"coverImage": null
}
},
{
"node": {
"coverImage": null
}
}
]
}
},
"errors": [
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 31,
"column": 9
}
],
"path": [
"allWorkJson",
"edges",
1,
"node",
"coverImage"
]
},
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 31,
"column": 9
}
],
"path": [
"allWorkJson",
"edges",
2,
"node",
"coverImage"
]
},
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 31,
"column": 9
}
],
"path": [
"allWorkJson",
"edges",
4,
"node",
"coverImage"
]
},
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 31,
"column": 9
}
],
"path": [
"allWorkJson",
"edges",
5,
"node",
"coverImage"
]
},
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 31,
"column": 9
}
],
"path": [
"allWorkJson",
"edges",
6,
"node",
"coverImage"
]
}
]
}
@KyleAMathews I don't know. How can I find out?
The file + line number are in the stack trace
All I have is this error from before, but here is the full stracktrace:
GraphQL Error:
[ { TypeError: Path must be a string. Received undefined
at assertPath (path.js:7:11)
at Object.resolve (path.js:1146:7)
at resolve (/Users/me/project/node_modules/gatsby/dist/schema/infer-graphql-type.js:335:41)
at resolveOrError (/Users/me/project/node_modules/graphql/execution/execute.js:474:12)
at resolveField (/Users/me/project/node_modules/graphql/execution/execute.js:460:16)
at /Users/me/project/node_modules/graphql/execution/execute.js:275:18
at Array.reduce (native)
at executeFields (/Users/me/project/node_modules/graphql/execution/execute.js:272:42)
at collectAndExecuteSubfields (/Users/me/project/node_modules/graphql/execution/execute.js:722:10)
at completeObjectValue (/Users/me/project/node_modules/graphql/execution/execute.js:704:10)
at completeValue (/Users/me/project/node_modules/graphql/execution/execute.js:601:12)
at completeValueWithLocatedError (/Users/me/project/node_modules/graphql/execution/execute.js:519:21)
at completeValueCatchingError (/Users/me/project/node_modules/graphql/execution/execute.js:494:21)
at resolveField (/Users/me/project/node_modules/graphql/execution/execute.js:462:10)
at /Users/me/project/node_modules/graphql/execution/execute.js:275:18
at Array.reduce (native)
message: 'Path must be a string. Received undefined',
locations: [ [Object] ],
path: [ 'allWorkJson', 'edges', 1, 'node', 'coverImage' ] },
Right โ when debugging, it's most often your (or our) code that's the problem. So ignore all the graphql-specific code and find the Gatsby specific line of code.
Which in this case is /Users/me/project/node_modules/gatsby/dist/schema/infer-graphql-type.js. Try opening that in your editor and go to line 335 and see what's happening there.
The error suggests we're calling a function with undefined so we need to add a check to fail early to prevent this.
this occurs for me when testing stuff. The resolvers have context which, in a few places, Gatsby assumes has a path on it, I presume because it should if the query is run correctly with the processed Page
@KyleAMathews line 335 is the last line in this fragment
// Look for fields that are pointing at a file โ if the field has a known
// extension then assume it should be a file field.
//
// TODO probably should just check if the referenced file exists
// only then turn this into a field field.
function inferFromUri(key, types) {
var fileField = types.find(function (type) {
return type.name === `File`;
});
if (!fileField) return;
return {
type: fileField.nodeObjectType,
resolve: function resolve(node, a, _ref5) {
var path = _ref5.path;
var fieldValue = node[key];
// Find File node for this node (we assume the node is something
// like markdown which would be a child node of a File node).
var parentFileNode = _.find(getNodes(), function (n) {
return n.type === `File` && n.id === node.parent;
});
// Use the parent File node to create the absolute path to
// the linked file.
var fileLinkPath = slash(nodePath.resolve(parentFileNode.dir, fieldValue));
Yeah, looks like we just need to check if fieldValue exists and return null if not.
Could you create a PR for this?
(and check of course that it solves your problem)
Seems to solve that problem ๐ #952
But I am now also seeing another error since updating my 1.0 to the HEAD today. Maybe this looks familiar to you guys? Otherwise I'll investigate further. I'm seeing this in the browser (and the console) when I load the page
ReferenceError: plugins is not defined
at module.exports (/Users/me/project/.cache/api-runner-ssr.js:11:17)
at /Users/me/project/node_modules/gatsby/dist/utils/develop.js:83:55
at Layer.handle [as handle_request] (/Users/me/project/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/me/project/node_modules/express/lib/router/index.js:317:13)
at /Users/me/project/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/Users/me/project/node_modules/express/lib/router/index.js:335:12)
at next (/Users/me/project/node_modules/express/lib/router/index.js:275:10)
at middleware (/Users/me/project/node_modules/webpack-hot-middleware/middleware.js:26:48)
at Layer.handle [as handle_request] (/Users/me/project/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/me/project/node_modules/express/lib/router/index.js:317:13)
at /Users/me/project/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/Users/me/project/node_modules/express/lib/router/index.js:335:12)
at next (/Users/me/project/node_modules/express/lib/router/index.js:275:10)
at expressInit (/Users/me/project/node_modules/express/lib/middleware/init.js:40:5)
at Layer.handle [as handle_request] (/Users/me/project/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/Users/me/project/node_modules/express/lib/router/index.js:317:13)
I haven't seen that error... it looks weird since api-runner-ssr is just for server rendering so should never be loaded into the browser.
Weird, it points to this line
// During bootstrap, we write requires at top of this file which looks like:
// var plugins = [
// require('/path/to/plugin1/gatsby-ssr.js'),
// require('/path/to/plugin2/gatsby-ssr.js'),
// ]
module.exports = function (api, args, defaultReturn) {
// Run each plugin in series.
var results = plugins.map(function (plugin) {
This sounds like it should be a new issue :-)
Having somehow similar issue! was trying to get my head around sharp-plugin using GatsbyGram. I've changed the data structure (image property as follow):
[
...
{
...
"image": {
"filepath": "images/3.jpg",
"caption": "blablabla"
}
...
}
...
]
and then query it like
{
allPostsJson {
edges {
node {
image{
filepath {
childImageSharp{
responsiveSizes(maxWidth: 640){
src
srcSet
}
}
}
}
}
}
}
}
and received
{
"errors": [
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 6,
"column": 11
}
],
"path": [
"allPostsJson",
"edges",
0,
"node",
"image",
"filepath"
]
},
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 6,
"column": 11
}
],
"path": [
"allPostsJson",
"edges",
1,
"node",
"image",
"filepath"
]
},
{
"message": "Path must be a string. Received undefined",
"locations": [
{
"line": 6,
"column": 11
}
],
"path": [
"allPostsJson",
"edges",
2,
"node",
"image",
"filepath"
]
}
],
"data": {
"allPostsJson": {
"edges": [
{
"node": {
"image": {
"filepath": null
}
}
},
{
"node": {
"image": {
"filepath": null
}
}
},
{
"node": {
"image": {
"filepath": null
}
}
}
]
}
}
}
anything I am missing? btw, all images exist in right directory.
@amirhouieh oh hmmm that's tricky. It's an error somewhere deep in Gatsby. Try looking through https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby/src/schema/run-sift.js (where queries are run (mostly) as it looks like an error that's happening during the running of queries. It might be a bug so would love a PR fixing things!