bar width by units and symbolic x coords not getting along

The problem starts here:

\def\pgfplots@bar@mathparse@#1#2{%
  \pgfmathparse{\pgfkeysvalueof{/pgf/#2}}%
  \ifpgfmathunitsdeclared
  \else
      \edef\pgfplots@bar@direction@choice@{#1}%
      \if N\pgfplots@bar@direction@choice@%
          \if a\pgfplots@bar@direction@choice
          \else
              \if x\pgfplots@bar@direction@choice
                  \def\pgfplots@bar@direction@choice@{y}%
              \else
                  \if y\pgfplots@bar@direction@choice
                      \def\pgfplots@bar@direction@choice@{x}%
                  \else
                      \pgfplotsthrow{invalid argument}{\pgfplots@bar@direction@choice@}{Sorry, the value of 'bar direction' is invalid}\pgfeov%
                  \fi
              \fi
          \fi
      \fi
      \if N\pgfplots@bar@direction@choice@%
          \pgfplots@bar@mathparse@error{#1}{#2}%
      \else
          \let\pgfplots@loc@TMPa=\pgfmathresult
          % ↓↓↓ notice this line ↓↓↓
          \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{\pgfplots@loc@TMPa}%
          % ↑↑↑ notice this line ↑↑↑
          \let\pgfplots@loc@TMPa=\pgfmathresult
          \if\pgfplots@bar@direction@choice@ x%   
              \pgfqpointxy@orig{\pgfplots@loc@TMPa}{0}%
              \edef\pgfmathresult{\pgf@sys@tonumber\pgf@x}%
          \else
              \pgfqpointxy@orig{0}{\pgfplots@loc@TMPa}%
              \edef\pgfmathresult{\pgf@sys@tonumber\pgf@y}%
          \fi
          %\edef\pgfplots@loc@TMPa{{\pgf@sys@tonumber\pgf@x}{\pgf@sys@tonumber\pgf@y}}%
          %\expandafter\pgfmathveclen@\pgfplots@loc@TMPa
      \fi
  \fi
}%

By using this macro, pgfplots will calculate the correct width of ybars, especially if the width is given in relative value.

This is why you can see \csname pgfplotstransformdirection ... in the code. This macro is defined by x coord trafo or so. It will translate the input x-coordinate to physical coordinate. Usually the input is a number, (1.2); sometimes it is a date (2017-1-23); in your case it should be symbolic (b).

But your input is 1, which is not a pre-defined symbolic coordinate, so you see the error.

To get over this, one cannot simply pass bar width=b because \pgfmathparse does not know what is b. Some possible solutions include:

  • wait until the package updates; or

  • redefined \pgfplots@bar@mathparse@ by replacing the transform line by

        % ↓↓↓ notice this line ↓↓↓
        \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{[normalized]\pgfplots@loc@TMPa}%  
        % ↑↑↑ notice this line ↑↑↑

And this is even better

        \ifx\pgfplots@symb@magic@prefix\undefined % test if symbolic coordinate
            \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{\pgfplots@loc@TMPa}%
        \else
            \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{[normalized]\pgfplots@loc@TMPa}%
        \fi

An MWE

\documentclass{scrartcl}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}

\begin{document}

\makeatletter

\def\pgfplots@bar@mathparse@#1#2{%
    \pgfmathparse{\pgfkeysvalueof{/pgf/#2}}%
    \ifpgfmathunitsdeclared
    \else
        \edef\pgfplots@bar@direction@choice@{#1}%
        \if N\pgfplots@bar@direction@choice@%
            \if a\pgfplots@bar@direction@choice
            \else
                \if x\pgfplots@bar@direction@choice
                    \def\pgfplots@bar@direction@choice@{y}%
                \else
                    \if y\pgfplots@bar@direction@choice
                        \def\pgfplots@bar@direction@choice@{x}%
                    \else
                        \pgfplotsthrow{invalid argument}{\pgfplots@bar@direction@choice@}{Sorry, the value of 'bar direction' is invalid}\pgfeov%
                    \fi
                \fi
            \fi
        \fi
        \if N\pgfplots@bar@direction@choice@%
            \pgfplots@bar@mathparse@error{#1}{#2}%
        \else
            \let\pgfplots@loc@TMPa=\pgfmathresult
            \ifx\pgfplots@symb@magic@prefix\undefined
                \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{\pgfplots@loc@TMPa}%
            \else
                \csname pgfplotstransformdirection\pgfplots@bar@direction@choice@\endcsname{[normalized]\pgfplots@loc@TMPa}%
            \fi
            \let\pgfplots@loc@TMPa=\pgfmathresult
            \if\pgfplots@bar@direction@choice@ x%   
                \pgfqpointxy@orig{\pgfplots@loc@TMPa}{0}%
                \edef\pgfmathresult{\pgf@sys@tonumber\pgf@x}%
            \else
                \pgfqpointxy@orig{0}{\pgfplots@loc@TMPa}%
                \edef\pgfmathresult{\pgf@sys@tonumber\pgf@y}%
            \fi
        \fi
    \fi
}%

\begin{tikzpicture}
    \begin{axis}[
        ybar stacked,
        bar width=1,
        symbolic x coords={a,b,c,d,e,f,g},
    ]
    \addplot coordinates {
        (a, 39.000000)
        (b, 30.200000)
        (c, 39.000000)
        (d, 30.200000)
        (e, 33.300000)
        (f, 30.000000)
        (g, 32.900000)
    };
    \end{axis}
\end{tikzpicture}

\begin{tikzpicture}
    \begin{axis}[
        ybar stacked,
        bar width=1,
        xticklabels={a,b,c,d,e,f,g},
        xtick=data, % a tick for each bar
        typeset ticklabels with strut % all xticklabels on the same baseline
    ]
    \addplot coordinates {
        (1, 39.000000)
        (2, 30.200000)
        (3, 39.000000)
        (4, 30.200000)
        (5, 33.300000)
        (6, 30.000000)
        (7, 32.900000)
    };
    \end{axis}
\end{tikzpicture}

\end{document}