Getting 'Unexpected token \ in JSON at position 1'

Hi - I’m trying to install a local version. I’ve installed the CLI but hit the ‘Unexpected token \ in JSON at position 1’ error as soon as I ghost install local.
Here’s the error log:
Debug Information:
OS: Mac OS X, v10.15.2
Node Version: v12.14.0
Ghost-CLI Version: 1.13.1
Environment: production
Command: ‘ghost install local’

An error occurred.
Message: 'Unexpected token \ in JSON at position 1'

Stack: SyntaxError: Unexpected token \ in JSON at position 1
at JSON.parse (<anonymous>)
at exports.parse (/usr/local/lib/node_modules/ghost-cli/node_modules/rc/lib/utils.js:15:17)
at addConfigFile (/usr/local/lib/node_modules/ghost-cli/node_modules/rc/index.js:30:20)
at Array.forEach (<anonymous>)
at module.exports (/usr/local/lib/node_modules/ghost-cli/node_modules/rc/index.js:43:36)
at registryUrl (/usr/local/lib/node_modules/ghost-cli/node_modules/registry-url/index.js:5:17)
at packageJson (/usr/local/lib/node_modules/ghost-cli/node_modules/package-json/index.js:40:46)
at lastestVersion (/usr/local/lib/node_modules/ghost-cli/node_modules/latest-version/index.js:5:26)
at Task.task (/usr/local/lib/node_modules/ghost-cli/lib/utils/pre-checks.js:20:21)
at /usr/local/lib/node_modules/ghost-cli/node_modules/listr/lib/task.js:167:30
at processTicksAndRejections (internal/process/task_queues.js:93:5)

I’m not great at this so any help would be appreciated!

Hi there :wave:. You may have better luck by using v10.x of Node as recommended in our installation docs:

Hi David
I’ve downgraded to node v10 as recommended but I’m still getting the same errors:

Debug Information:
OS: Mac OS X, v10.15.2
Node Version: v10.18.0
Ghost-CLI Version: 1.13.1
Environment: production
Command: 'ghost install local'

An error occurred.
Message: 'Unexpected token \ in JSON at position 1'

Stack: SyntaxError: Unexpected token \ in JSON at position 1
at JSON.parse (<anonymous>)
at exports.parse (/usr/local/share/.config/yarn/global/node_modules/rc/lib/utils.js:15:17)
at addConfigFile (/usr/local/share/.config/yarn/global/node_modules/rc/index.js:30:20)
at Array.forEach (<anonymous>)
at module.exports (/usr/local/share/.config/yarn/global/node_modules/rc/index.js:43:36)
at registryUrl (/usr/local/share/.config/yarn/global/node_modules/registry-url/index.js:5:17)
at packageJson (/usr/local/share/.config/yarn/global/node_modules/package-json/index.js:40:46)
at lastestVersion (/usr/local/share/.config/yarn/global/node_modules/latest-version/index.js:5:26)
at Task.task (/usr/local/share/.config/yarn/global/node_modules/ghost-cli/lib/utils/pre-checks.js:20:21)
at Promise.resolve.then.then.skipped (/usr/local/share/.config/yarn/global/node_modules/listr/lib/task.js:167:30)
at process._tickCallback (internal/process/next_tick.js:68:7)

Any ideas?
Thanks

It looks like one of your config files might be messed up… Can you edit

/usr/local/share/.config/yarn/global/node_modules/rc/lib/utils.js

And insert this line before line 30 (configs.push(parse(fileConfig)))

console.log('Adding config file:', fileConfig)

The command will still fail, but it will hopefully print all of the config files that are processed so we can narrow down the issue :)

Hi,
I don’t see any fileConfig in that file - line 30 is completely different too.
Here’s the content of that file:

'use strict';
var fs   = require('fs')
var ini  = require('ini')
var path = require('path')
var stripJsonComments = require('strip-json-comments')

var parse = exports.parse = function (content) {

  //if it ends in .json or starts with { then it must be json.
  //must be done this way, because ini accepts everything.
  //can't just try and parse it and let it throw if it's not ini.
  //everything is ini. even json with a syntax error.

  if(/^\s*{/.test(content))
    return JSON.parse(stripJsonComments(content))
  return ini.parse(content)

}

var file = exports.file = function () {
  var args = [].slice.call(arguments).filter(function (arg) { return arg != null })

  //path.join breaks if it's a not a string, so just skip this.
  for(var i in args)
    if('string' !== typeof args[i])
      return

  var file = path.join.apply(null, args)
  var content
  try {
    return fs.readFileSync(file,'utf-8')
  } catch (err) {
    return
  }
}

var json = exports.json = function () {
  var content = file.apply(null, arguments)
  return content ? parse(content) : null
}

var env = exports.env = function (prefix, env) {
  env = env || process.env
  var obj = {}
  var l = prefix.length
  for(var k in env) {
    if(k.toLowerCase().indexOf(prefix.toLowerCase()) === 0) {

      var keypath = k.substring(l).split('__')

      // Trim empty strings from keypath array
      var _emptyStringIndex
      while ((_emptyStringIndex=keypath.indexOf('')) > -1) {
        keypath.splice(_emptyStringIndex, 1)
      }

      var cursor = obj
      keypath.forEach(function _buildSubObj(_subkey,i){

        // (check for _subkey first so we ignore empty strings)
        // (check for cursor to avoid assignment to primitive objects)
        if (!_subkey || typeof cursor !== 'object')
          return

        // If this is the last key, just stuff the value in there
        // Assigns actual value from env variable to final key
        // (unless it's just an empty string- in that case use the last valid key)
        if (i === keypath.length-1)
          cursor[_subkey] = env[k]


        // Build sub-object if nothing already exists at the keypath
        if (cursor[_subkey] === undefined)
          cursor[_subkey] = {}

        // Increment cursor used to track the object at the current depth
        cursor = cursor[_subkey]

      })

    }

  }

  return obj
}

var find = exports.find = function () {
  var rel = path.join.apply(null, [].slice.call(arguments))

  function find(start, rel) {
    var file = path.join(start, rel)
    try {
      fs.statSync(file)
      return file
    } catch (err) {
      if(path.dirname(start) !== start) // root
        return find(path.dirname(start), rel)
    }
  }
  return find(process.cwd(), rel)
}

Wrong file :man_facepalming: Here’s the correct file!

/usr/local/lib/node_modules/ghost-cli/node_modules/rc/index.js

Hi again - I’ve found the correct file and added the console.log… but where will the output be shown? It’s not in the error log?!
thanks.

It should be printed when you run the command (ghost install local)

Nope, it’s still the same message and the same content in the error log too. So, it seems the addConfigFile function is not being fired.

I just noticed that the logs have different paths (the first one uses /usr/local/lib/… and the second /usr/local/share/.config/yarn.global)… I have a feeling it’s because of the change in node version.

Try modifying this file: /usr/local/share/.config/yarn/global/node_modules/rc/index.js

That worked!
…and I think it may have something to do with artifactory

Here’s the output:
Adding config file: {\rtf1\ansi\ansicpg1252\cocoartf1671\cocoasubrtf600
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{*\expandedcolortbl;;}
\paperw11900\paperh16840\margl1440\margr1440\vieww10800\viewh8400\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\pardirnatural\partightenfactor0

\f0\fs24 \cf0 registry=https://artifactory.myworkcompany.com/api/npm/npm/
save-exact=true}

I’ve changed the domain as I’m not sure about any security issues it may expose… I’m not a dev I’m a designer :wink:
If that is the cause, how do I change it or somehow ignore it?

We’re making progress! It’s definitely an issue with artifactory. That file is a “Rich Text File”, and a CLI dependency is trying to read it as a configuration file.

You can modify the line I had you add to be console.log('Adding config file:', {file, fileConfig}) so you can see exactly what the file is. You might have to temporarily move it while Ghost does its magic :grimacing:

Yes, I forgot it was in a .npmrc doc that I created a while ago when I was working from home and needed to install some components from the work repo.
I removed the .npmrc doc and everything now works - thank you very much for your guidance!

1 Like

Glad you got it working! Good luck with Ghost :ghost:

1 Like