Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

panic: runtime error: index out of range [1] with length 1 #1341

Closed
landure opened this issue Sep 15, 2022 · 4 comments
Closed

panic: runtime error: index out of range [1] with length 1 #1341

landure opened this issue Sep 15, 2022 · 4 comments
Labels

Comments

@landure
Copy link

landure commented Sep 15, 2022

When trying to add a additionnal tag to a xml file, yq crash with the error panic: runtime error: index out of range [1] with length 1.

Version of yq: 4.27.5
Operating system: Ubuntu 22.04 Impish Indri
Installed via: binary ( yq_linux_amd64.tar.gz )

Input document

File: /etc/iwatch/iwatch.xml

<config charset="utf-8">
  <guard email="iwatch@localhost" name="iWatch"></guard>
  <watchlist><title>Operating System</title></watchlist>
</config>

Command

sudo yq --inplace --input-format='xml' --output-format='xml' \
  'eval' ".config.watchlist |= . + [ {
      \"title\": \"Some title\"
    } ]" \
  "/etc/iwatch/iwatch.xml"

Actual behavior

panic: runtime error: index out of range [1] with length 1

goroutine 1 [running]:
github.com/mikefarah/yq/v4/pkg/yqlib.addMaps(0xc0002aab80, 0xc00033ac20?, 0x40d51f?)
        /home/runner/work/yq/yq/pkg/yqlib/operator_add.go:189 +0x3c6
github.com/mikefarah/yq/v4/pkg/yqlib.add(0xc000282450?, {0xc00035cb40, 0xc00035cbd0, 0x1, {0x0, 0x0}}, 0xc0002aa800, 0xc0002aa880)
        /home/runner/work/yq/yq/pkg/yqlib/operator_add.go:65 +0x510
github.com/mikefarah/yq/v4/pkg/yqlib.resultsForRHS(0x19?, {0xc00035cb40, 0xc00035cbd0, 0x1, {0x0, 0x0}}, 0x28?, {0x0, 0x0, 0x8bbdd0}, ...)
        /home/runner/work/yq/yq/pkg/yqlib/operators.go:105 +0x62a
github.com/mikefarah/yq/v4/pkg/yqlib.doCrossFunc(0x1d?, {0xc00035cb40, 0xc00035cbd0, 0x1, {0x0, 0x0}}, 0xc000288468, {0x0, 0x0, 0x8bbdd0})
        /home/runner/work/yq/yq/pkg/yqlib/operators.go:142 +0x413
github.com/mikefarah/yq/v4/pkg/yqlib.crossFunctionWithPrefs(0x1?, {0xc00035ca20, 0xc00035c870, 0x1, {0x0, 0x0}}, 0xc00035c8d0?, {0x0, 0x0, 0x8bbdd0})
        /home/runner/work/yq/yq/pkg/yqlib/operators.go:175 +0x3db
github.com/mikefarah/yq/v4/pkg/yqlib.crossFunction(0xc000282450?, {0xc00035ca20, 0xc00035c870, 0x1, {0x0, 0x0}}, 0x0?, 0xc5a5a0?, 0x70?)
        /home/runner/work/yq/yq/pkg/yqlib/operators.go:153 +0x9f
github.com/mikefarah/yq/v4/pkg/yqlib.addOperator(0xc000282450?, {0xc00035c7e0, 0xc00035c870, 0x0, {0x0, 0x0}}, 0x0?)
        /home/runner/work/yq/yq/pkg/yqlib/operator_add.go:46 +0x1c5
github.com/mikefarah/yq/v4/pkg/yqlib.(*dataTreeNavigator).GetMatchingNodes(0xc000282450?, {0xc00035c7e0, 0xc00035c870, 0x0, {0x0, 0x0}}, 0xc000288468)
        /home/runner/work/yq/yq/pkg/yqlib/data_tree_navigator.go:37 +0x25c
github.com/mikefarah/yq/v4/pkg/yqlib.assignUpdateOperator(0xc000282450?, {0xc00035c3f0, 0x0, 0x0, {0x0, 0x0}}, 0xc000288480)
        /home/runner/work/yq/yq/pkg/yqlib/operator_assign.go:52 +0x56e
github.com/mikefarah/yq/v4/pkg/yqlib.(*dataTreeNavigator).GetMatchingNodes(0x0?, {0xc00035c3f0, 0x0, 0x0, {0x0, 0x0}}, 0xc000288480)
        /home/runner/work/yq/yq/pkg/yqlib/data_tree_navigator.go:37 +0x25c
github.com/mikefarah/yq/v4/pkg/yqlib.(*streamEvaluator).Evaluate(0xc000229cf0, {0x7ffc9d60d7f9, 0x16}, {0x93cbe0?, 0xc000286600?}, 0x7f13e90a6cc8?, {0x93ee38, 0xc0002864e0}, {0x0, 0x0}, ...)
        /home/runner/work/yq/yq/pkg/yqlib/stream_evaluator.go:124 +0x363
github.com/mikefarah/yq/v4/pkg/yqlib.(*streamEvaluator).EvaluateFiles(0xc00028a4d0?, {0x7ffc9d60d7bc, 0x3c}, {0xc0002c0010, 0x1, 0xc0002a0800?}, {0x93ee38, 0xc0002864e0}, 0xec?, {0x93e0a8, ...})
        /home/runner/work/yq/yq/pkg/yqlib/stream_evaluator.go:73 +0x30e
github.com/mikefarah/yq/v4/cmd.evaluateSequence(0xc0002a4280?, {0xc0002c0000, 0x2, 0x5})
        /home/runner/work/yq/yq/cmd/evalute_sequence_command.go:132 +0x8a5
github.com/spf13/cobra.(*Command).execute(0xc0002a4280, {0xc0002863c0, 0x5, 0x6})
        /home/runner/go/pkg/mod/github.com/spf13/cobra@v1.5.0/command.go:872 +0x694
github.com/spf13/cobra.(*Command).ExecuteC(0xc0002a4000)
        /home/runner/go/pkg/mod/github.com/spf13/cobra@v1.5.0/command.go:990 +0x3bd
github.com/spf13/cobra.(*Command).Execute(...)
        /home/runner/go/pkg/mod/github.com/spf13/cobra@v1.5.0/command.go:918
main.main()
        /home/runner/work/yq/yq/yq.go:22 +0x1e5

Expected behavior

<config charset="utf-8">
  <guard email="iwatch@localhost" name="iWatch"></guard>
  <watchlist>
    <title>Operating System</title>
  </watchlist>
  <watchlist>
    <title>Some title</title>
  </watchlist>
</config>

Additional context
When there is two watchlist tags in the input document, the command works without issue.

<config charset="utf-8">
  <guard email="iwatch@localhost" name="iWatch"></guard>
  <watchlist><title>Operating System</title></watchlist>
  <watchlist><title>Some other title</title></watchlist>
</config>
@mikefarah
Copy link
Owner

Ah I see - there are two issues here.

  1. If there's a single item in the XML, yq has no way of knowing that it's an array of one. So watchlist in the first example is a map, but in the second example, it's an array.
  2. I failed to add validation when adding to a map that the right hand side is a map (fix in next release).

To get what you want, you have to wrap watchlist into an array (if it's not one already) and then append to it:

yq  -p=xml -o=xml '.config.watchlist |= (select(tag == "!!seq") // [.]) + [{"x": "y"}]' file.xml

The key bit is: (select(tag == "!!seq") // [.]) which will use watchlist as-is if it's a sequence, otherwise it will wrap it into an array.

@landure
Copy link
Author

landure commented Sep 16, 2022

Thank you for you help. The only drawback of your command is that when "watchlist" is not present, it add a <watchlist>null</watchlist> tag to the XML in addition to the new content.

I managed to fix this by using:

yq  -p=xml -o=xml '.config.watchlist |= (select(tag == "!!seq") // [ select(length > 0) ]) + [{"x": "y"}]' file.xml

Thank you for your work on yq, it is a great tool to programmatically edit yaml, json and xml files :)

@mikefarah
Copy link
Owner

Pleasure :)
That's an easy fix as well - I'm not at my pc with yq atm but it will be something like:

yq  -p=xml -o=xml 'select(has(.config.watchlist)) | .config.watchlist |= (select(tag == "!!seq") // [.]) + [{"x": "y"}]' file.xml

@mikefarah
Copy link
Owner

Fixed in 4.28.2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants